【NLP】Python中文文本聚类

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/sinat_40431164/article/details/81092288

1. 准备需要进行聚类的文本,这里选取了10篇微博。

import os
path = 'E:/work/@@@@/开发事宜/大数据平台/5. 标签设计/文本测试数据/微博/'
titles = []
files = []
for filename in os.listdir(path):
    titles.append(filename)
    #带BOM的utf-8编码的txt文件时开头会有一个多余的字符\ufeff,BOM被解码为一个字符\ufeff,如何去掉?修改encoding为utf-8_sig或者utf_8_sig
    filestr = open(path + filename, encoding='utf-8_sig').read()
    files.append(filestr)
for i in range(len(titles)):
    print(i, titles[i], files[i])

0 #我有特别的推倒技巧#之佟掌柜收李逍遥.txt 【#我有特别的推倒技巧#之佟掌柜收李逍遥】@胡歌 此前对南都称,“我要海陆空三栖”,可是还没等他征服海陆空呢,@素描闫妮 就把他先收了……他俩主演的电视剧《生活启示录》收视率稳居卫视黄金档排行第1名,在豆瓣甚至被刷到了8 .6的高分。佟掌柜是怎么推倒李逍遥而又不违和的?http://t.cn/Rvbj6oy
1 从前的称是16两为一斤,为什么要16两为一斤呢?.txt 从前的称是16两为一斤,为什么要16两为一斤呢?古人把北斗七星、南斗六星以及福、禄、寿三星,共16颗星比作16两,商人卖东西,要讲究商德,不能缺斤短两;如果耍手腕,克扣一两就减福,克扣二两就损禄,克扣三两就折寿。所以这个数字和古代人对诚信的美好愿望分不开。
2 作死男晒酒驾.txt #作死男晒酒驾# “他还晒出自己闯红灯20多次,最终此人自首。”请问“亲爱的交警同志”你们在干神马事情去啦!!!是不是撞死人呢,你们才会管啊,开宝马的命太金贵了,而我们的命太.......!!![怒][泪] |作死男晒酒驾
3 冀中星被移送检察院审查起诉.txt #新闻追踪#:【冀中星被移送检察院审查起诉】首都机场公安分局对冀中星爆炸案侦查终结,目前已移送朝阳检察院审查起诉。7月20日18时24分,冀中星在首都机场T3航站楼B口外引爆自制炸药。案发当天除冀中星左手腕因被炸截肢外,无其他人伤亡。7月29日,冀中星因涉嫌爆炸罪被批捕。http://t.cn/zQHjr0S
4 宝马男微博炫富晒酒驾挑逗交警 最终因被人肉求饶[汗].txt 【宝马男微博炫富晒酒驾挑逗交警 最终因被人肉求饶[汗]】"开车喝酒是不是违反交规?@深圳交警 今晚猎虎吗?",在向交警挑衅后,他又晒出车牌号,称自己闯红灯20多次,随即遭人肉,并陆续被曝光私人信息。很快,他发微博求饶。26日,交警传唤该男子,该男子炫富违法车辆已被查扣。http://t.cn/Rvb9gF6
5 广场舞出口世界.txt #广场舞出口世界# 澳大利亚引进广场舞顺带引进大妈的疑惑:1)是否可以申请技术移民2)是否属于物种入侵3)亚洲女子天团进入澳洲是否会影响当地娱乐圈的圈态平衡4)是否能够接受“中国大妈一旦引进,一概不退不换”的要求
6 方舟子:锤子改口号,换汤不换药!.txt 【方舟子:锤子改口号,换汤不换药!】遭到方舟子举报虚假宣传后,锤子手机官网修改了宣传口号,将"东半球最好用的手机"改成"全球第二好用的智能手机"。对此,方舟子称,被举报后,罗永浩一边说着"呵呵",一边偷偷改了广告用语,改成了”全球第二好用的智能手机"等,但这仍然是换汤不换药的虚假广告..
7 杜汶泽宣布暂别香港 (2).txt #杜汶泽宣布暂别香港#杜先生长的丑,嘴巴臭,爪子贱不是你的错,你出来吓人乱说话熏到人就是你的不对了,大陆人怎么了,大陆人敢作敢当说不安逸你就不安逸你,大陆人让你无地自容的本事还是绰绰有余的,滚吧,杜狗! 
8 杜汶泽宣布暂别香港.txt #杜汶泽宣布暂别香港# 虽说言论自由无可厚非,但攻击民族种族国家,涉及歧视他人的行为仍然不是营销策略中可以突破的下线。把无耻当有趣,是多无聊的人才能干出的事儿啊!该。。只有这个字能概括。
9 首都机场爆炸案嫌犯冀中星 移送检方审查起诉.txt #豫广微新闻#【首都机场爆炸案嫌犯冀中星 移送检方审查起诉】 据报道,首都机场公安分局对冀中星爆炸案侦查终结,目前已移送朝阳检察院审查起诉。7月20日,山东籍男子冀中星在首都机场T3航站楼引爆自制炸药,案发当天除冀中星左手腕因被炸截肢外,无其他人伤亡

2. 创建方法封装jieba分词,注意还需要获得用户自定义词和停用词列表

此步骤会在分词时将用户自定义的词看作一个整体,不会分开,比如在添加“佟掌柜”这个词之前,会将其分词成“佟”、“掌柜”,添加该词后会将“佟掌柜视为整体”。且分词后的list会过滤掉停用词列表中的词,这样像标点符号等没有意义的字或字符就不会出现在最终的集合中。

# 创建停用词list  
def stopwordslist(stopwords_filepath):  
    stopwords = [line.strip() for line in open(stopwords_filepath, 'r', encoding='utf-8').readlines()]  
    return stopwords  

# 对句子进行分词
def segment(text, userdict_filepath = "userdict2.txt", stopwords_filepath = 'stopwords.txt'):
    import jieba
    jieba.load_userdict(userdict_filepath)
    stopwords = stopwordslist(stopwords_filepath)  # 这里加载停用词的路径
    seg_list = jieba.cut(text, cut_all=False)
    seg_list_without_stopwords = []
    for word in seg_list:  
        if word not in stopwords:  
            if word != '\t':  
                seg_list_without_stopwords.append(word)    
    return seg_list_without_stopwords

用户自定义字典,命名为userdict2.txt,保存在项目文件夹下

杜汶泽
佟掌柜
南都
生活启示录
第1名
违和
两
南斗六星
福禄寿三星
颗
酒驾
晒出
亲爱的
命
金贵
冀中星
7月20日
T3航站楼
B口
案发当天
7月29日
微博
炫富
广场舞
物种入侵
虚假
宣传口号
好用
不对
大陆人
才能
干出
能
微新闻
被炸

停用词列表:https://blog.csdn.net/shijiebei2009/article/details/39696571,命名为stopwords.txt,保存在项目文件夹下

3. 使用分词器将list of files进行分词

totalvocab_tokenized = []
for i in files:
    allwords_tokenized = segment(i, "userdict2.txt", 'stopwords.txt')
    totalvocab_tokenized.extend(allwords_tokenized)
print(len(totalvocab_tokenized)) #去重前长度371,去重后256

371

4. 获得Tf-idf矩阵

from sklearn.feature_extraction.text import TfidfVectorizer
#max_df: When building the vocabulary ignore terms that have a document frequency strictly higher than the given threshold (corpus-specific stop words). If float, the parameter represents a proportion of documents, integer absolute counts. This parameter is ignored if vocabulary is not None.
#min_df: When building the vocabulary ignore terms that have a document frequency strictly lower than the given threshold. This value is also called cut-off in the literature. If float, the parameter represents a proportion of documents, integer absolute counts. This parameter is ignored if vocabulary is not None.
tfidf_vectorizer = TfidfVectorizer(max_df=0.9, max_features=200000,
                                 min_df=0.1, stop_words='english',
                                 use_idf=True, tokenizer=segment)
#terms is just a 集合 of the features used in the tf-idf matrix. This is a vocabulary
#terms = tfidf_vectorizer.get_feature_names() #长度258
tfidf_matrix = tfidf_vectorizer.fit_transform(files) #fit the vectorizer to synopses
print(tfidf_matrix.shape) #(10, 258):10篇文档,258个feature

(10, 258)

5. 计算文档相似性

from sklearn.metrics.pairwise import cosine_similarity
#Note that 有了 dist 就可以测量任意两个或多个概要之间的相似性.
#cosine_similarity返回An array with shape (n_samples_X, n_samples_Y)
dist = 1 - cosine_similarity(tfidf_matrix)

6. 获得分类

from scipy.cluster.hierarchy import ward, dendrogram, linkage
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['Microsoft YaHei'] #用来正常显示中文标签
#Perform Ward's linkage on a condensed distance matrix.
#linkage_matrix = ward(dist) #define the linkage_matrix using ward clustering pre-computed distances
#Method 'ward' requires the distance metric to be Euclidean
linkage_matrix = linkage(dist, method='ward', metric='euclidean', optimal_ordering=False)
#Z[i] will tell us which clusters were merged, let's take a look at the first two points that were merged
#We can see that ach row of the resulting array has the format [idx1, idx2, dist, sample_count]
print(linkage_matrix)
for index, title in enumerate(titles):
    print(index, title)

[[ 3.          9.          0.35350366  2.        ]
 [ 2.          4.          1.08521531  2.        ]
 [ 7.          8.          1.2902641   2.        ]
 [ 0.          5.          1.39239608  2.        ]
 [ 1.          6.          1.40430097  2.        ]
 [13.         14.          1.42131068  4.        ]
 [12.         15.          1.4744491   6.        ]
 [11.         16.          1.62772682  8.        ]
 [10.         17.          2.2853395  10.        ]]

0 #我有特别的推倒技巧#之佟掌柜收李逍遥.txt
1 从前的称是16两为一斤,为什么要16两为一斤呢?.txt
2 作死男晒酒驾.txt
3 冀中星被移送检察院审查起诉.txt
4 宝马男微博炫富晒酒驾挑逗交警 最终因被人肉求饶[汗].txt
5 广场舞出口世界.txt
6 方舟子:锤子改口号,换汤不换药!.txt
7 杜汶泽宣布暂别香港 (2).txt
8 杜汶泽宣布暂别香港.txt
9 首都机场爆炸案嫌犯冀中星 移送检方审查起诉.txt

7. 可视化

plt.figure(figsize=(25, 10))
plt.title('中文文本层次聚类树状图')
plt.xlabel('微博标题')
plt.ylabel('距离(越低表示文本越类似)')
dendrogram(
    linkage_matrix,
    labels=titles, 
    leaf_rotation=-70,  # rotates the x axis labels
    leaf_font_size=12  # font size for the x axis labels
)
plt.show()
plt.close()

展开阅读全文

没有更多推荐了,返回首页