文本聚类算法

文本聚类算法分类

1、划分法(基于划分的聚类算法)

给定一个有N个元组或者纪录的数据集,分裂法将构造K个分组,每一个分组就代表一个聚类,K<N。而且这K个分组满足下列条件:(1)每一个分组至少包含一个数据纪录;(2)每一个数据纪录属于且仅属于一个分组(注意:这个要求在某些模糊聚类算法中可以放宽);对于给定的K,算法首先给出一个初始的分组方法,以后通过反复迭代的方法改变分组,使得每一次改进之后的分组方案都较前一次好,而所谓好的标准就是:同一分组中的记录越近越好,而不同分组中的记录越远越好。

使用这个基本思想的算法有:K-Means算法、K-MEDOIDS算法、CLARANS算法。

2、层次法(基于层次的聚类算法)

这种方法对给定的数据集进行层次似的分解,直到某种条件满足为止。具体可分为“自底向上”和“自顶向下”两种方案,即合并聚类(由下而上)和分裂聚类(由上而下)。

合并层次聚类是将语料库中的任一数据都当作一个新的簇,计算所有簇相互之间的相似度,然后将相似度最大的两个簇进行合并,重复这个步骤直到达到某个终止条件,因此合并聚类方法也被称为由下而上的方法。

分裂聚类恰好与合并聚类进行相反的操作,它是一种由上而下的方法,该方法先将数据集中所有的对象都归为同一簇,并将不断地对原来的簇进行划分从而得到更小的簇,直到满足最初设定的某个终止条件。

层次聚类法的优点:
(1)适用于发现任意形状的簇
(2)适用于任意形式的相似度或距离表示形式
(3)聚类粒度的灵活性
缺点:
(1)算法终止的条件很模糊,难以精确表达并控制算法的停止
(2)一旦聚类结果形成,一般不再重新构建层次结构来提高聚类的性能
(3)难以处理大规模数据,也不能适应动态数据集的处理。
由于层次聚类算法简单,因此针对它的研究也比较多,也提出了不少改进算法,主要方向就是将该策略与其他聚类策略相结合从而形成多层聚类。

代表算法有:BIRCH算法、CURE算法、CHAMELEON算法等。

3、基于密度的方法

基于密度的方法与其他方法的一个根本区别是:它不是基于各种各样的距离的,而是基于密度的。这样就能克服基于距离的算法智能发现“类圆形”的缺点。这个方法的指导思想就是,只要一个区域中的点的密度大过某个阈值,就把它加到与之相近的聚类中去。

代表算法有:DBSCAN算法、OPTICS算法、DENCLUE算法等。

4、基于网格的方法

这种方法首先将数据空间划分成为有限个单元(cell)的网格结构,所有的处理都是以单个的单元为对象的。这么处理的一个突出的优点就是处理速度很快,通常这是与目标数据库中记录的个数无关的,它只与数据空间分为多少个单元有关。

代表算法有:STING算法、CLIQUE算法、WAVE-CLUSTER算法。

5、基于模型的方法

基于模型的方法给每一个聚类假定一个模型,然后去寻找一个能很好的满足这个模型的数据集。这样一个模型可能是数据点在空间中的密度分布函数或者其他。它的一个潜在的假定就是:目标数据集是由一系列的概率分布

使用DBSCAN进行文本聚类

DBSCAN 算法介绍

典型的基于密度的算法是DBSCAN算法,该算法基本思想是:对于一个类中的每一个对象,在其给定半径R的区域中包含的对象数目不小于某一给定的最小数目,即在DBSCAN中,一个类被认为是密度大于一个给定阈值的一组对象的集合,能够被其中的任意一个核心对象所确定。DBSCAN算法执行时,先从数据集w中找到任意一个对象q,并查找w中关于R和最小下限数MinPts的从q密度到达的所有对象。如果q是核心对象,也就是说,q半径为R的领域中包含的对象数不少于MinPts,则根据算法可以找到一个关于参数R和MinPts的类。如果q是一个边界点,即q半径为R的领域包含的对象数小于MinPts,则没有对象从q密度到达,q被暂时标注为噪声点。然后,DBSCAN处理数据集W中的下一个对象。

DBSCAN聚类算法存在如下缺点:

  1. 随着对于大数据量的应用,需要有很大的内存支持与I/O开销。
  2. 由于使用了全局参数R和MinPts,因此没有考虑数据密度和类别距离大小的不均匀性,所以DBSCAN算法很难得到高质量的聚类结果。
  3. 算法参数过于复杂,领域外人员很难理解和掌握。

DBSCAN再详细的原理介绍可以看文章尾部我参考的资料。

DBSCAN python实现

import jieba
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.cluster import DBSCAN

def makesentence(sentence):
    sentence_seged = jieba.cut(sentence)
    stopwords = []  # 这里加载停用词的路径
    outstr = ''
    for word in sentence_seged:
        if word not in stopwords:
                outstr += word
                outstr += " "
    seg_list = outstr
    return seg_list

def tf_idf(corpus_file):
    docs = []
    with open(corpus_file, 'r', encoding="utf-8", errors='ignore')as fr:
        text = fr.read().strip().replace('\n', '').replace(' ', '')
        doc = makesentence(text)
        if len(doc) > 0:
            docs.append(doc)

    Vectorizer = CountVectorizer()
    transformer = TfidfTransformer()
    tfidf = transformer.fit_transform(Vectorizer.fit_transform(docs))
    weight = tfidf.toarray()
    return weight

def dbs(tf_weight):
	"""
    :param tf_weight:  进过tf-idf计算后的权值矩阵
    :return: 句子聚类后标签
    """
    dbs_clf = DBSCAN(eps=0.5, min_samples=4)
    dbs_clf.fit(tf_weight)
    # print(dbs_clf.labels_)
    return dbs_clf.labels_

上面最后一个是调用sklearn提刚DBSCAN工具, 输出的dbs_clf.labels_就是聚类后各个文本的标签。输入的参数就两个,eps:表示聚类类别中样本的相似度衡量。min_samples:表示每个聚类类别中的最小样本数。这两个值如何取,一般人工手动调试。
在参考的文章中也写到一种方法sorted k-dist 来确定这两个值,我在实验过程中这个方法取的值聚类出来只剩一类了(测试文章我选的是混合10的类文章),这里我也把这个方法贴出来一下。通过绘制的sorted k-dist图,用肉眼观察曲线的分布,当出现第一个谷点时,则该点即可作为临界点,对应的距离可以作为Eps的取值,另外,k即可作为MinPts的取值。下面代码中k值需要不断调试。

import numpy as np
from tqdm import tqdm
import matplotlib.pyplot as plt


def k_dist_plot(data, k=4):
    """
    绘制k-dist图
    :param data: 向量化后的数据,可以是tf-idf向量化后,也可以是Word2vec向量化后. [np.array or csr_matrix]
    :param k: 第k个近邻
    :return:
    """
    k_list = []
    for i in tqdm(range(len(data))):
        dist = np.square(data[i, :] - data)
        dist = np.sqrt(np.sum(dist, axis=-1))
        this_k_dist = np.sort(dist)[k + 1]
        k_list.append(this_k_dist)

    k_list = sorted(k_list, reverse=True)
    plt.switch_backend('agg')
    plt.figure()
    plt.plot(range(len(k_list)), k_list, 'b-')
    plt.xlabel('points')
    plt.ylabel('k-dist')
    plt.show()

使用K-Means进行文本聚类

k-Means 算法介绍

K-means算法是一种典型的基于划分的聚类算法,该聚类算法的基本思想是在聚类开始时根据用户预设的类簇数目k随机地在所有文本集当中选择k个对象,将这些对象作为k个初始类簇的平均值或者中心,对于文本集中剩余的每个对象,根据对象到每一个类簇中心的欧几里得距离,划分到最近的类簇中;全部分配完之后,重新计算每个类簇的平均值或者中心,再计算每篇文本距离这些新的类簇平均值或中心的距离,将文本重新归入目前最近的类簇中;不断重复这个过程,直到所有的样本都不能再重新分配为止。

K-means算法优点:
(1)对待处理文本的输入顺序不太敏感
(2)对凸型聚类有较好结果
(3)可在任意范围内进行聚类。

缺点:
(1)对初始聚类中心的选取比较敏感,往往得不到全局最优解,得到的多是次 优解
(2)关于算法需要预先设定的k值,限定了聚类结果中话题的个数,这在非给定语料的应用中并不可行
(3)该算法容易受到异常点的干扰而造成结果的严重偏差
(4)算法缺少可伸缩性

K-means Python实现

from sklearn.cluster import KMeans

# sklearn_K-means聚类
def k_means(tf_weight, K):
    """
    :param tf_weight: 经过向量化的数据,可以通过tf-idf,也可以通过word2vec
    :param K:  需要提取指定的聚类数目
    :return: 各文本对应的标签
    """
    n_clusters = K
    clf = KMeans(n_clusters, max_iter=300, n_init=40, init='k-means++')
    s = clf.fit(tf_weight)
    print(s)
    # 中心点
    print(clf.cluster_centers_)
    # 每个样本所属的簇
    print(clf.labels_)

    return clf.labels_.tolist()

上述Python实现都是通过现有的工具包,理解原理也可以自己手写

文章作为自己在学习过程中的学习笔记
参考文章链接:
DBSCAN文本聚类与python实现
文本聚类算法总结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值