数学原理:
向量:空间中有两个点原点O和点A,OA(O指向A)就是一个向量,向量是有长度有方向的。
点积(内积):
向量长度: ||A||= sqrt() = 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:
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])