參加完數(shù)模之后休息了幾天,今天繼續(xù)看TF-IDF算法。上篇中對(duì)TF-IDF算法已經(jīng)做了詳細(xì)的介紹,在此不再贅述。今天主要是通過(guò)python,結(jié)合sklearn庫(kù)實(shí)現(xiàn)該算法,并通過(guò)k-means算法實(shí)現(xiàn)簡(jiǎn)單的文檔聚類。 一 結(jié)巴分詞 1.簡(jiǎn)述 中文分詞是中文文本處理的一個(gè)基礎(chǔ)性工作,長(zhǎng)久以來(lái),在Python編程領(lǐng)域,一直缺少高準(zhǔn)確率、高效率的分詞組建,結(jié)巴分詞正是為了滿足這一需求而提出。 2.安裝 (1)全自動(dòng)安裝 在安裝了easy—stall的情況之下可以全自動(dòng)安裝:easy_install jieba (2)半自動(dòng)安裝 ·下載地址:https://pypi./pypi/jieba/ ·在cmd下找到具體的目錄python setup.py安裝 3.功能 (1)全模式:將句子中所有的可以成詞的詞語(yǔ)都掃描出來(lái),速度非???,但是不能解決歧義問(wèn)題; jieba.cut方法接收兩個(gè)參數(shù):第一個(gè)參數(shù)為需要分詞的字符串,第二個(gè)cut_all參數(shù)用來(lái)控制是否采用全模式進(jìn)行分詞。 >>> #coding:utf-8
>>> import jieba
>>> seg_list = jieba.cut("我愛(ài)西郵西郵愛(ài)我",cut_all = True)
>>> print "Full Mode:","/".join(seg_list)
Full Mode: 我/愛(ài)/西/郵/西/郵/愛(ài)/我 (2)精確模式:將句子最精確分開(kāi),適合文本分析: >>> seg_list = jieba.cut("喜歡玩游戲,可以把編程當(dāng)成玩游戲,還挺好玩的,哈哈哈哈")
>>> print "Default Mode:", "/ ".join(seg_list)
Default Mode: 喜歡/ 玩游戲/ ,/ 可以/ 把/ 編程/ 當(dāng)成/ 玩游戲/ ,/ 還/ 挺好玩/ 的/ ,/ 哈哈哈哈 除此之外,默認(rèn)表示的也是精確模式: >>> seg_list = jieba.cut("喜歡玩游戲,可以把編程當(dāng)成玩游戲,還挺好玩的,哈哈哈哈")
>>> print ",".join(seg_list)
(3)搜索引擎模式:在精確模式的基礎(chǔ)上,對(duì)長(zhǎng)詞再次切分 ,提高召回率。 jieba.cut_for_search方法只接收需要分詞的字符串,這種方法分詞分的比較細(xì): >>> seg_list = jieba.cut_for_search("西郵就是西安郵電大學(xué)的簡(jiǎn)稱")
>>> print ",".join(seg_list)
結(jié)果:西郵,就是,西安,郵電,電大,大學(xué),郵電大學(xué),的,簡(jiǎn)稱 當(dāng)然結(jié)巴分詞還有很多功能,比如添加字典啊什么的,在此不再詳細(xì)說(shuō)明。 二 scikit-learn scikit-learn含有完善的文檔和豐富的機(jī)器學(xué)習(xí)算法,已經(jīng)實(shí)現(xiàn)了所有基本的機(jī)器學(xué)習(xí)算法,并且其本身就帶有一些標(biāo)準(zhǔn)的數(shù)據(jù)集。比如用來(lái)分類的iris數(shù)據(jù)集、digits數(shù)據(jù)集;用來(lái)回歸的boston house price 數(shù)據(jù)集。 更多內(nèi)容見(jiàn)http:///20071.html。 三 python實(shí)現(xiàn)TF-IDF算法 之前用的是python3.4,但由于不可抗的原因,又投入了2.7的懷抱,在這里編寫(xiě)一段代碼,簡(jiǎn)單的實(shí)現(xiàn)TF-IDF算法。大致的實(shí)現(xiàn)過(guò)程是讀入一個(gè)測(cè)試文檔,計(jì)算出文檔中出現(xiàn)的詞的tfidf值,并保存在另一個(gè)文檔中。 # -*- coding: cp936 -*-
import jieba
import jieba.posseg as pseg
import os
import sys
from sklearn import feature_extraction
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.feature_extraction.text import CountVectorizer
import sys
reload(sys)
sys.setdefaultencoding( "utf-8" )
sys.path.append("C:\Users\Administrator\Desktop\9.17")
from numpy import *
fr = open('exercise.txt')
fr_list = fr.read()
dataList = fr_list.split('\n')
data = []
for oneline in dataList:
data.append(" ".join(jieba.cut(oneline)))
#將得到的詞語(yǔ)轉(zhuǎn)換為詞頻矩陣
freWord = CountVectorizer()
#統(tǒng)計(jì)每個(gè)詞語(yǔ)的tf-idf權(quán)值
transformer = TfidfTransformer()
#計(jì)算出tf-idf(第一個(gè)fit_transform),并將其轉(zhuǎn)換為tf-idf矩陣(第二個(gè)fit_transformer)
tfidf = transformer.fit_transform(freWord.fit_transform(data))
#獲取詞袋模型中的所有詞語(yǔ)
word = freWord.get_feature_names()
#得到權(quán)重
weight = tfidf.toarray()
tfidfDict = {}
for i in range(len(weight)):
for j in range(len(word)):
getWord = word[j]
getValue = weight[i][j]
if getValue != 0:
if tfidfDict.has_key(getWord):
tfidfDict[getword] += string.atof(getValue)
else:
tfidfDict.update({getWord:getValue})
sorted_tfidf = sorted(tfidfDict.iteritems(),
key = lambda d:d[1],reverse = True)
fw = open('result.txt','w')
for i in sorted_tfidf:
fw.write(i[0] + '\t' + str(i[1]) +'\n')
至此,對(duì)算法已經(jīng)有了一個(gè)簡(jiǎn)單的實(shí)現(xiàn),接下來(lái)需要做的是將其應(yīng)用到文檔聚類中加以運(yùn)用。 四 實(shí)現(xiàn)簡(jiǎn)單的文本聚類 要聚類,聚什么是重點(diǎn)!結(jié)合上述分析,我們可以將一篇文章中的關(guān)鍵詞和對(duì)應(yīng)的tf-idf值一一對(duì)應(yīng)起來(lái),顯然想到的是dict,那么聚類是聚的當(dāng)然不止一篇文章,那么我們就可以分別將每篇文章的關(guān)鍵詞和對(duì)應(yīng)的tf-idf值對(duì)應(yīng)起來(lái),最后整合起來(lái)進(jìn)行聚類,當(dāng)然還是得用到dict。 結(jié)合上述tf-idf的實(shí)現(xiàn),可以將得到的結(jié)果分別存在同一個(gè)目錄下的.txt中,導(dǎo)入目錄讀取并整合,直接上代碼: # -*- coding: cp936 -*-
#-*- coding:utf-8 -*-
from PIL import Image,ImageDraw
import os, codecs, random
from math import sqrt
#將得到的結(jié)果按照字典存放
rows_norms = {}
def readfile(dirname):
rows = {}
for f in os.listdir(dirname):#目錄
fr = codecs.open(dirname + f,'r',encoding = 'utf-8')
tw_dict = {}
norm = 0
for line in fr:
items = line.split('\t')
token = items[0].strip()
if len(token)<2:
continue
w = float(items[1].strip())
norm = w**2
tw_dict[token] = w
rows[str(f[:-4])] = tw_dict
rows_norms[str(f[:-4])] = sqrt(float(norm))
#print len(rows)
return rows
至此,相當(dāng)于得到了數(shù)據(jù),接下來(lái)就是k-means算法的實(shí)現(xiàn)了,之前的文章中都有詳細(xì)說(shuō)明,在此不再贅述,所不同的是在此采用了余弦距離計(jì)算相似度: #得到余弦距離,其中v1就是row,v2是聚類中心點(diǎn)
def cosine(v1,norm_v1,v2,norm_v2):
if norm_v1 == 0 or norm_v2 == 0:
return 1.0
dividend = 0
for k,v in v1.items():
for k in v2:
dividend += v*v2[k]
return 1.0-dividend/(norm_v1*norm_v2)
主程序段如下: #算法的實(shí)現(xiàn)
def kcluster(rows,distance=cosine,k=3):
ranges=rows_range(rows)
#初始化聚類中心
clusters=[]
for i in range(k):
clusters.append(random_vec(ranges))
clusteres_norm=[]
for i in range(k):
clusteres_norm.append(norm(clusters[i]))
lastmatches=None
#開(kāi)始迭代
for t in range(300):
print '第%d次迭代' % t
bestmatches=[[] for i in range(k)]
for j in rows.keys():
row=rows[j]
row_norm=rows_norms[j]
bestmatch=0
min_dis=10000000
for i in range(k):
d=distance(row, row_norm, clusters[i],clusteres_norm[i])
if d<min_dis:
bestmatch=i
min_dis=d
bestmatches[bestmatch].append(j)
if bestmatches==lastmatches:
break
lastmatches=bestmatches
for i in range(k):
clusters[i]=center(bestmatches[i], rows)
print bestmatches
return bestmatches
#test
if __name__ == '__main__':
corpus_dir='D:/python2.7/exercise/clusting/data/'
rows=readfile(corpus_dir)
print 'create vectorspace'
n=3
clust=kcluster(rows,k=n)
簡(jiǎn)單測(cè)試,結(jié)果還是挺理想的,但還是可以結(jié)合之前對(duì)k-means算法的優(yōu)化,實(shí)現(xiàn)更好的聚類。
|
|
來(lái)自: 昵稱10504424 > 《工作》