1. 程式人生 > >機器學習分類演算法(一)——餘弦相似度

機器學習分類演算法(一)——餘弦相似度

概述:餘弦相似度是通過測量兩個向量點積空間夾角的餘弦值來判斷相似性。0°角的餘弦值是1,90°為0,餘弦值大小在[-1,1]區間。

數學原理:

       向量:空間中有兩個點原點O和點A,OA(O指向A)就是一個向量,向量是有長度有方向的。

       點積(內積): <O,A> = ∑(Oi*Ai)

       向量長度: ||A||= sqrt(<A,A>) = sqrt(∑A*A)

       餘弦公式: cos(α) = A*B / ||A||*||B|| = ∑Ai*Bi / sqrt(∑A*A)*sqrt(∑B*B)

應用舉例:文字新聞分類

原理:將爬出來的文章用jieba分詞庫分好詞,然後去除停用詞,再用map把詞頻進行統計,利用已分好類別的文章和當前待分類文章的詞條詞頻進行餘弦相似度計算,根據計算結果將文章分類。

步驟:

1.    用爬蟲爬好一定數量的文章

2.    先開啟已知某類文章並用jieba庫進行分詞操作

file1 = open(filename)  #先讀檔案
file_str = file1.read() #檔案字串
file_str = Unicode(file_str,’utf-8’) #文字編碼轉成utf-8
file1.close() #關閉檔案
#jieba庫的使用之cut,將目標字串分解返回一個生成器,第二個引數是是#否完全分割,預設false
seglist = jieba.cut(file_str,cut_all = False)
#jieba.cut_for_search(str) 是以搜尋引擎模式分割
strlist = “,”.join(seglist)#將返回的分詞生成器轉換成字串中間用‘,’分開


3.    載入停用詞檔案

file2  = open(tingyongci_file_at) #開啟停用詞檔案
#像操作剛才的待讀文字一樣進行處理 不過停用詞檔案每行一個停用詞
所以停用詞以換行符為單位分割儲存到stop_str裡
file2_str = file2.read()
file2_str = Unicode(file2_str,’utf-8’)
file2.close()
stop_str = file2_str.split(‘\n’)


ps:什麼是停用詞,又有什麼作用?

  

如圖,就是這樣的無實際意義、大多起連線作用、去除並不影響語意理解的詞

4. 去除停用詞並將有用的詞條放到map中進行詞頻統計

t_allword = {} #不計數僅僅統計詞條

allword = {} #當前文章中所有出現的有效詞條map,並且已計數

for myword in strlist.split(','):
       if not(myword.strip() in stop_str) and len(myword.strip()) > 1:
       <span style="white-space:pre">	</span>   t_allword.setdefault(myword,0)
           all_word.setdefault(myword,0)
           all_word[myword] += 1


5.    此時已知類別的標本文章已經處理完畢,接下來對未分類文章進行同樣的處理:jieba分詞、去除停用詞並加入map進行詞條詞頻統計。

6.    將已知分類文章map和當前待分類文章map進行餘弦相似度計算,也就是將map的key放到list裡,也就是對應每個詞條的詞頻,將文章特徵數字化也就可以進行餘弦相似度計算了。

def cos_like(x,y): #計算餘弦相似度函式
 tx = np.array(x)
 ty = np.array(y)
 cos1 = np.sum(tx*ty)
   cos21 = np.sqrt(sum(tx**2))
   cos22 = np.sqrt(sum(ty**2))
 returncos1/float(cos21*cos22)


完整程式碼:

# -*- coding: utf-8 -*-
'''
Created on 2015-11-17
 
@author: haoran
'''
import copy
import jieba
import numpy as np
from os import listdir
 
tingyongci_file_at = 'text_test/tingyongci.txt'
filename = 'text_test/junshi1.txt'
 
file2 = open(tingyongci_file_at)
file2_str = file2.read()
file2_str = unicode(file2_str,'utf-8')
file2.close()
stop_str = file2_str.split('\n')    #停用詞列表
 
def cos_like(x,y):
    tx= np.array(x)
    ty= np.array(y)
   cos1 = np.sum(tx*ty)
   cos21 = np.sqrt(sum(tx**2))
   cos22 = np.sqrt(sum(ty**2))
    return cos1/float(cos21*cos22)
 
def ret_main_guanjianci(filename):   #返回主樣本關鍵詞map和temp_map
   file1 = open(filename)
   file_str = file1.read()
   file_str = unicode(file_str,'utf-8')
   file1.close()
   seglist = jieba.cut(file_str,cut_all=False)
    print type(seglist)
   strlist = ",".join(seglist)
 
   t_allword = {}
   all_word = {}
    for myword in strlist.split(','):
       if not(myword.strip() in stop_str) and len(myword.strip()) > 1:
           t_allword.setdefault(myword,0)
           all_word.setdefault(myword,0)
           all_word[myword] += 1
    return t_allword,all_word
 
def ret_yangben_guanjianci(file_at,t_allword):   #返回待測樣本的關鍵字map
   ret_word = copy.deepcopy(t_allword)
    file= open(file_at)   
   string = file.read()
   string = unicode(string,'utf-8')
   file.close()
    #print string
   fenci = jieba.cut(string)
    for myword in fenci:
       if not(myword.strip() in stop_str):
           if ret_word.has_key(myword):
                ret_word[myword]+=1
    return ret_word
 
def compare_main(main_file,comp_file):
   t_allword,all_word = ret_main_guanjianci(main_file)
   alldata = []
   compdata = []
   t_word = ret_yangben_guanjianci(comp_file,t_allword)
    for key in all_word.keys():
       alldata.append(all_word[key])
       compdata.append(t_word[key])
    print alldata
    print compdata
   ans1 = cos_like(alldata,compdata)
    print '%s文字和 %s文字相似度為 %f'%(main_file,comp_file,ans1)
 
 
 
futherfolder = 'text_test'
files = listdir(futherfolder)
n = len(files)
for i in range(0,n-1):
   compare_main(futherfolder+'/'+files[3],futherfolder+'/'+files[i])