基於 K-Means 演算法的文字聚類
先粘一篇我的實驗報告,其中涉及的細節,有時間再提出來總結
實驗內容:基於K-Means演算法的文字聚類
實驗要求:
1、 能夠從社交媒體或網上給定的資料集(資料集已給定),從中挖掘出新聞話題,如線上檢測微博訊息中大量突現的關鍵字,並將它們進行聚類,從而找到若干個新聞話題。
2、 給定一個新聞資訊或報道作為測試樣本,測試其所屬的報道分類。
3、 最終要求有訓練集,測試集,聚類模型和相關原始碼及簡要說明。
4、 系統實現包含預處理,特徵提取,訓練時採用的聚類模型,測試時採用的分類模型。
5、 報告內容包括:實現流程,概要設計,關鍵模組詳細設計實現。
6、 提交時以壓縮包形式,需包括:系統實現原始碼(包含清晰註釋),訓練集和測試集,實驗報告等三部分內容。壓縮包命名方式:學號-姓名-班級.rar
實驗預備知識: Python基本語法
K-means聚類演算法相關知識
基於TF-IDF演算法的特徵提取
文件相似度計算
實驗環境: Windows10作業系統Python2.7 IDLE
一、 實現流程
二、 概要設計
1、 讀取訓練集文字內容
讀取給定資料集資料夾中每一個文件後,將文字內容寫入一個Result.txt,每一行為一個文件,方便後面詞頻矩陣的處理。
2、 文字預處理
讀取之前存放所有文字內容的Result.txt,將其內容去空格,去標點,並用結巴進行分詞。
3、 特徵提取
使用scikit-learn工具呼叫CountVectorizer()和TfidfTransformer()函式計算TF-IDF值,將文字轉為詞頻矩陣,矩陣元素a[i][j] 表示j詞在i類文字下的詞頻。將詞頻矩陣儲存在TF-IDF_Result文件中。
4、 K-Means聚類
,對文字根據瀏覽內容後的經驗分為3類,呼叫sklearn.cluster實現,並儲存該聚類模型,對測試集使用
5、 測試集分類
使用clf.fit_predict 方法測試測試集文字。
三、 關鍵模組詳細設計實現
1、 特徵提取
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.feature_extraction.text import CountVectorizer
# 將文字中的詞語轉換為詞頻矩陣 矩陣元素a[i][j] 表示j詞在i類文字下的詞頻
vectorizer = CountVectorizer()
# 該類會統計每個詞語的tf-idf權值
transformer = TfidfTransformer()
# 第一個fit_transform是計算tf-idf 第二個fit_transform是將文字轉為詞頻矩陣
tfidf=transformer.fit_transform(vectorizer.fit_transform(corpus))
# 獲取詞袋模型中的所有詞語
word = vectorizer.get_feature_names()
# 將tf-idf矩陣抽取出來,元素w[i][j]表示j詞在i類文字中的tf-idf權重
weight = tfidf.toarray()
2、 聚類模型
from sklearn.cluster import KMeans
from sklearn.externals import joblib
def K_Means(weight):
print 'Start Kmeans:'
# 選擇3箇中心點
clf = KMeans(n_clusters=3)
# clf.fit(X)可以把資料輸入到分類器裡
clf.fit(weight)
# 3箇中心點
print 'cluster_center:'
print(clf.cluster_centers_)
# 每個樣本所屬的簇
# print(clf.labels_)
print'list_number label '
i = 1
while i <= len(clf.labels_):
print i,' ',clf.labels_[i - 1]
i = i + 1
# 用來評估簇的個數是否合適,距離越小說明簇分的越好,選取臨界點的簇個數
print 'inertia:'
print(clf.inertia_)
# 儲存模型
joblib.dump(clf, 'km.pkl')
四、 結果展示
1、聚類結果
注:訓練集在train資料夾中
2、 分類結果
注:測試集在test資料夾中
六、實驗原始碼
# *- coding: utf-8 -*-
import sys
import os
import jieba
import jieba.analyse
import codecs
import re
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.feature_extraction.text import CountVectorizer
from zhon.hanzi import punctuation
from sklearn.cluster import KMeans
from sklearn.externals import joblib
reload(sys)
sys.setdefaultencoding('utf8')
# Step1:Read file
def read_file():
path = "train\\C4-Literature\\"
resName = "Result.txt"
if os.path.exists(resName):
os.remove(resName)
result = codecs.open(resName, 'w', 'utf-8')
num = 1
while num <= 33:
name = "C4-Literature%d" % num
fileName = path + str(name) + ".txt"
source = open(fileName, 'r')
line = source.readline().decode('GB2312')
line = line.strip('\n')
line = line.strip('\r')
while line != "":
line = line.encode('utf-8')
line = line.replace('\n', ' ')
line = line.replace('\r', ' ')
result.write(line + ' ')
line = source.readline().decode('GB2312')
else:
result.write('\r\n')
source.close()
num = num + 1
else:
result.close()
return resName
# Step2:cut file and get feature vector matrixes
def get_TFIDF(resname,filename):
corpus = [] # 語料庫 空格連線
# 讀取語料 一行為一個文件
for line in open(resname, 'r').readlines():
line=line.strip() # 刪除末尾的'/n'
string = re.sub(ur"[%s]+" % punctuation, "", line.decode("utf-8")) # 去標點
seg_list = jieba.cut(string,cut_all=False) # 結巴分詞
corpus.append(' '.join(seg_list))
# 將文字中的詞語轉換為詞頻矩陣 矩陣元素a[i][j] 表示j詞在i類文字下的詞頻
vectorizer = CountVectorizer()
# 該類會統計每個詞語的tf-idf權值
transformer = TfidfTransformer()
# 第一個fit_transform是計算tf-idf 第二個fit_transform是將文字轉為詞頻矩陣
tfidf = transformer.fit_transform(vectorizer.fit_transform(corpus))
# 獲取詞袋模型中的所有詞語
word = vectorizer.get_feature_names()
# 將tf-idf矩陣抽取出來,元素w[i][j]表示j詞在i類文字中的tf-idf權重
weight = tfidf.toarray()
# fileName = "TF-IDF_Result.txt"
result = codecs.open(filename, 'w', 'utf-8')
for j in range(len(word)):
result.write(word[j] + ' ')
result.write('\r\n\r\n')
# 列印每類文字的tf-idf詞語權重,第一個for遍歷所有文字,第二個for便利某一類文字下的詞語權重
for i in range(len(weight)):
for j in range(len(word)):
result.write(str(weight[i][j]) + ' ')
result.write('\r\n\r\n')
result.close()
return weight
# Step3:Clustering
def K_Means(weight):
print 'Start Kmeans:'
# 選擇3箇中心點
clf = KMeans(n_clusters=3)
# clf.fit(X)可以把資料輸入到分類器裡
clf.fit(weight)
# 3箇中心點
print 'cluster_center:'
print(clf.cluster_centers_)
# 每個樣本所屬的簇
# print(clf.labels_)
print'list_number label '
i = 1
while i <= len(clf.labels_):
print i,' ',clf.labels_[i - 1]
i = i + 1
# 用來評估簇的個數是否合適,距離越小說明簇分的越好,選取臨界點的簇個數
print 'inertia:'
print(clf.inertia_)
# 儲存模型
joblib.dump(clf, 'km.pkl')
# Step4:Test
def test():
path = "test\\"
test_name = "test_result.txt"
file_name = "test_TF-IDF.txt"
if os.path.exists(test_name):
os.remove(test_name)
test_result = codecs.open(test_name,'w','utf-8')
for file in os.listdir(path):
source = open(path + file,'r')
line = source.readline().decode('GB2312')
line = line.strip('\n')
line = line.strip('\r')
while line !="":
line = line.encode('utf-8')
line = line.replace('\n',' ')
line = line.replace('\r',' ')
test_result.write(line + ' ')
line=source.readline().decode('GB2312')
else:
test_result.write('\n\r')
source.close()
test_result.close()
test_weight = get_TFIDF(test_name,file_name)
# 載入儲存的模型
clf = joblib.load('km.pkl')
clf.fit_predict(test_weight)
print'list_number label '
i = 1
while i <= len(clf.labels_):
print i, ' ', clf.labels_[i - 1]
i = i + 1
if __name__ == '__main__':
resName = read_file()
filename = "TF-IDF_Result.txt"
weight=get_TFIDF(resName,filename)
K_Means(weight)
test()