一 文本聚类简介
1.1、定义
文本聚类主要是依据著名的聚类假设:同类的文档相似度较大,而不同类的文档相似度较小。作为一种无监督的机器学习方法,聚类由于不需要训练过程,以及不需要预先对文档手工标注类别,因此具有一定的灵活性和较高的自动化处理能力,已经成为对文本信息进行有效地组织、摘要和导航的重要手段,为越来越多的研究人员所关注。(摘自百度百科)
1.2、应用领域
① 文档聚类可以作为多文档自动文摘等自然语言处理应用的预处理步骤
比较典型的例子是哥伦比亚大学开发的多文档文摘系统Newsblaster。Newsblaster将每天发生的重要新闻文本进行聚类处理,并对同主题文档进行冗余消除、信息融合、文本生成等处理,从而生成一篇简明扼要的摘要文档。
② 对搜索引擎返回的结果进行聚类,使用户迅速定位到所需要的信息
③ 对用户感兴趣的文档(如用户浏览器cache中的网页)聚类,从而发现用户的兴趣模式并用于信息过滤和信息主动推荐等服务
④ 聚类技术还可以用来改善文本分类的结果
⑤ 数字图书馆服务
通过SOM神经网络等方法,可以将高维空间的文档拓扑保序地映射到二维空间,使得聚类结果可视化和便于理解,如SOMlib[ ]系统;(以上摘自百度百科)
⑥ 用于大数据中热点话题或事件的发现
与文本分类不同,文本聚类预先并不知道聚出来的每个类别的主题具体是什么,只知道每个类别下的数据相似度较大,描述的是同一个主题。因此,文本聚类比较适合用于大数据中热点话题或事件的发现。
1.3、文本聚类方法
作为NLP领域最经典的使用场景之一,文本聚类形成了它的一般流程(图1)并积累了许多的实现方法。
从图1可以看出,文本聚类主要有一下几个步骤。
- 分词
- 去除停用词
- 构建词袋空间VSM(vector space model)
- TF-IDF构建词权重
- 使用聚类算法进行聚类(KMeans,DBSCAN,BIRCH等)
当然,也有在实际应用中考虑到文本向量维度较高不利于聚类等问题,增加pca降维的方法,如图2所示。
二 文本聚类的主要步骤
2.1 分词
分词这一步主要是对中文文档而言的,一般使用分词工具来完成。
一般的中文分词工具主要有:jieba,Hanlp,SnowNLP(MIT),pynlpir(大数据搜索挖掘实验室(北京市海量语言信息处理与云计算应用工程技术研究中心)),thulac(清华大学自然语言处理与社会人文计算实验室) 等。
2.2 去除停用词
所谓停用词就是我们在实际生活中常用的不能用于区分文档之间关系的一些词语。如“的”,“你”,“我”,“他”等。
常见的中文停用词有:
1. 中文停用词表(比较全面,有1208个停用词)
2. 最全中文停用词表整理(1893个)
示例代码:
def read_from_file(file_name):
with open(file_name,"r") as fp:
words = fp.read()
return words
def stop_words(stop_word_file):
words = read_from_file(stop_word_file)
result = jieba.cut(words)
new_words = []
for r in result:
new_words.append(r)
return set(new_words)
def del_stop_words(words,stop_words_set):
# words是已经切词但是没有去除停用词的文档。
# 返回的会是去除停用词后的剩余词
result = jieba.cut(words)
new_words = []
for r in result:
if r not in stop_words_set:
new_words.append(r)
return new_words
2.3 构建词袋空间VSM(vector space model)
构建词袋空间的步骤如下:
- 将所有文档读入到程序中,再将每个文档切词。
- 去除每个文档中的停用词。
- 统计所有文档的词集合(sk-learn有相关函数)。
- 对每个文档,都将构建一个向量,向量的值是对应词语在本文档中出现的次数。
示例代码:
def get_all_vector(file_path,stop_words_set):
names = [ os.path.join(file_path,f) for f in os.listdir(file_path) ]
posts = [ open(name).read() for name in names ]
docs = []
word_set = set()
for post in posts:
doc = del_stop_words(post,stop_words_set)
docs.append(doc)
word_set |= set(doc)
#print len(doc),len(word_set)
word_set = list(word_set)
docs_vsm = []
#for word in word_set[:30]:
#print word.encode("utf-8"),
for doc in docs:
temp_vector = []
for word in word_set:
temp_vector.append(doc.count(word) * 1.0)
#print temp_vector[-30:-1]
docs_vsm.append(temp_vector)
docs_matrix = np.array(docs_vsm)
2.4 TF-IDF构建词权重
前面已经得到了文本的向量化表示,但是只用词频进行数值化明显是不够的。因此,这里使用TF-IDF来度量每个词的重要程度。
关于TF-IDF的介绍可以参考网上的文章:
1. 基本文本聚类方法
2. TF-IDF百度百科
3. TF-IDF维基百科英文版(需要FQ)
示例代码如下:
column_sum = [ float(len(np.nonzero(docs_matrix[:,i])[0])) for i in range(docs_matrix.shape[1]) ]
column_sum = np.array(column_sum)
column_sum = docs_matrix.shape[0] / column_sum
idf = np.log(column_sum)
idf = np.diag(idf)
# 根据IDF的定义,计算词的IDF并不依赖于某个文档,所以我们提前计算好。
# 注意一下计算都是矩阵运算,不是单个变量的运算。
for doc_v in docs_matrix:
if doc_v.sum() == 0:
doc_v = doc_v / 1
else:
doc_v = doc_v / (doc_v.sum())
tfidf = np.dot(docs_matrix,idf)
return names,tfidf
2.5 使用聚类算法进行聚类
到了这一步,就可以使用聚类算法(KMeans,DBSCAN,BIRCH等)进行文本聚类了,在这里就不作详细介绍了。
三 小结
本文主要介绍了NLP中的文本聚类的基本方法。当然,除了使用TF-IDF构建词权重的方法之外,还可以使用LDA主题模型、Word2Vec等获取文本向量表示的方法进行文本聚类,这里就不再一一介绍了。