赞
踩
使用sklearn
基于TF_IDF算法,实现把文本变成向量。再使用sklearn的kmeans聚类算法进行文本聚类。
个人观点:这是比较古老的技术了,文本转向量的效果不如如今的 text2vec 文本转向量好。
而且sklearn 不支持GPU加速,处理大量数据速度极慢。
项目完整可运行代码:https://github.com/JieShenAI/csdn/blob/main/machine_learning/TF-IDF%20sklearn聚类.ipynb
import re
import random
import jieba
import pandas as pd
import numpy as np
from sklearn.feature_extraction.text import TfidfTransformer, TfidfVectorizer
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA
from sklearn.cluster import KMeans
import gensim
from gensim.models import Word2Vec
from sklearn.preprocessing import scale
import multiprocessing
语料库如下
corpus = [
'花呗更改绑定银行卡',
'我什么时候开通了花呗',
'A man is eating food.',
'A man is eating a piece of bread.',
'The girl is carrying a baby.',
'A man is riding a horse.',
'A woman is playing violin.',
'Two men pushed carts through the woods.',
'A man is riding a white horse on an enclosed ground.'
]
jieba 分词
jieba.add_word("花呗")
,给jieba添加花呗
, 不然 jieba 会把花呗拆分成'花', '呗'
。
分词模型,用起来还是有点麻烦
jieba.add_word("花呗") def preprocess_text(content_lines, sentences): for line in content_lines: try: segs=jieba.lcut(line) segs = [v for v in segs if not str(v).isdigit()]#去数字 segs = list(filter(lambda x:x.strip(), segs)) #去左右空格 segs = list(filter(lambda x:len(x)>1, segs)) #长度为1的字符 # segs = list(filter(lambda x:x not in stopwords, segs)) #去掉停用词 sentences.append(" ".join(segs)) except Exception: print(line) continue sentences = [] # 处理语料,语料的处理结果存放在sentences preprocess_text(corpus, sentences)
jieba 分词结果如下:
利用 TF_IDF 算法把分词结果转成向量
vectorizer = TfidfVectorizer(sublinear_tf=True, max_df=0.5)
#统计每个词语的tf-idf权值
transformer = TfidfTransformer()
# 第一个fit_transform是计算tf-idf 第二个fit_transform是将文本转为词频矩阵
tfidf = transformer.fit_transform(vectorizer.fit_transform(sentences))
# 获取词袋模型中的所有词语
word = vectorizer.get_feature_names_out()
# 将tf-idf矩阵抽取出来,元素w[i][j]表示j词在i类文本中的tf-idf权重
weight = tfidf.toarray()
#查看特征大小
print ('Features length: ' + str(len(word)))
如下图所示,向量矩阵过于稀疏了,没有worc2vec
编码的向量稠密。
编码的向量是33纬;
为了方便使用,在JieKmeans
类中封装了,kmeans聚类训练、预测和绘图功能。
from sklearn.decomposition import PCA class JieKmeans: def __init__(self, numClass=4, n_components=10, func_type='PCA'): #这里也可以选择随机初始化init="random" self.PCA = PCA(n_components=n_components) if func_type == 'PCA': self.func_plot = PCA(n_components=2) elif func_type == 'TSNE': from sklearn.manifold import TSNE self.func_plot = TSNE(2) self.numClass = numClass def plot_cluster(self, result, newData): plt.figure(2) Lab = [[] for i in range(self.numClass)] index = 0 for labi in result: Lab[labi].append(index) index += 1 color = ['oy', 'ob', 'og', 'cs', 'ms', 'bs', 'ks', 'ys', 'yv', 'mv', 'bv', 'kv', 'gv', 'y^', 'm^', 'b^', 'k^', 'g^'] * 3 for i in range(self.numClass): x1 = [] y1 = [] for ind1 in newData[Lab[i]]: # print ind1 try: y1.append(ind1[1]) x1.append(ind1[0]) except: pass plt.plot(x1, y1, color[i]) #绘制初始中心点 x1 = [] y1 = [] for ind1 in self.model.cluster_centers_: try: y1.append(ind1[1]) x1.append(ind1[0]) except: pass plt.plot(x1, y1, "rv") #绘制中心 plt.show() def train(self, data): tmp = self.PCA.fit_transform(data) self.model = KMeans( n_clusters=self.numClass, max_iter=10000, init="k-means++", tol=1e-6) s = self.model.fit(tmp) print("聚类算法训练完成\n", s) def predict(self, data): t_data = self.PCA.fit_transform(data) result = list(self.model.predict(t_data)) return result def plot(self, weight): t_data = self.PCA.fit_transform(weight) result = list(self.model.predict(t_data)) plot_pos = self.func_plot.fit_transform(weight) self.plot_cluster(result, plot_pos)
net = JieKmeans(
numClass=3, # 聚类类别
n_components=5,
func_type='PCA' # 绘图降纬方法
)
net.train(weight)
# net.plot(weight)
聚类可视化
net.plot(weight)
如上图所示,上图的可视化显示聚类效果很好,但是由于TF-IDF文本转向量的效果不是很好,所以上述聚类出来的结果可能并不是我们想要的。
预测结果:
p = net.predict(weight)
class_data = {
i:[]
for i in range(3)
}
for text,cls in zip(corpus, p):
class_data[cls.item()].append(text)
class_data
聚类结果如下:
点击即可阅读,基于word2vec 和 kmeans_pytorch 的文件聚类实现,利用GPU加速提高聚类速度
该文使用text2vec通过cuda加速,加快文本转向量的速度。使用kmeans_pytorch包,基于pytorch在GPU上计算,提高聚类速度。
如下是其基于word2vec的聚类结果:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。