美文网首页书房就是我的全世界搜索服务
中文NLP笔记:7. 如何做中文短文本聚类

中文NLP笔记:7. 如何做中文短文本聚类

作者: 不会停的蜗牛 | 来源:发表于2019-02-02 20:12 被阅读280次

    文本聚类

      将一个个文档表示成高维空间点,通过计算哪些点距离比较近,聚成一个簇,簇的中心叫做簇心

      一个好的聚类要保证簇内点的距离尽量的近,但簇与簇之间的点要尽量的远


    聚类一般步骤

      1. 引入依赖库

      一般有随机数库、jieba 分词、pandas 库等

      加载停用词字典,是个 stopwords.txt 文件,可以根据场景在该文本里面添加要去除的词(比如冠词、人称、数字等词)

      2. 语料加载

      3. 分词

      4. 去停用词

      5. 生成训练数据

      6. 将得到的数据集打散,生成更可靠的训练集分布,避免同类数据分布不均匀

      7. 抽取词向量特征,将文本中的词语转换为词频矩阵,统计每个词语的 tf-idf 权值,获得词在对应文本中的 tf-idf 权重


    用 TF-IDF 的中文文本 K-means 聚类

      使用 k-means++ 来初始化模型,然后通过 PCA 降维把上面的权重 weight 降到10维,进行聚类模型训练

      定义聚类结果可视化函数

      对数据降维到2维,然后获得结果,最后绘制聚类结果图

      得到的聚类结果图,可以看到4个中心点和4个簇

      降维使用了 PCA,我们还可以试试 TSNE,TSNE 保留下的属性信息,更具代表性,也即最能体现样本间的差异,但是 TSNE 运行极慢,PCA 则相对较快

      在展示高维数据时,常常先用 PCA 进行降维,再使用 TSNE


    实战代码

    1. 导入库,jieba 用于分词,还有计算 Tfidf 的包:

        import random
        import jieba
        import pandas as pd
        import numpy as np
        from sklearn.feature_extraction.text import TfidfTransformer
        from sklearn.feature_extraction.text import TfidfVectorizer
        import matplotlib.pyplot as plt
        from sklearn.decomposition import PCA
        from sklearn.cluster import KMeans
        from sklearn.preprocessing import scale
        import multiprocessing

    2. 加载停用词

    stopwords=pd.read_csv('stopwords.txt',index_col=False,quoting=3,sep="\t",names=['stopword'], encoding='utf-8')
        stopwords=stopwords['stopword'].values

    3. 加载语料

      #加载4个csv 文件
        laogong_df = pd.read_csv('beilaogongda.csv', encoding='utf-8', sep=',')
        laopo_df = pd.read_csv('beilaogongda.csv', encoding='utf-8', sep=',')
        erzi_df = pd.read_csv('beierzida.csv', encoding='utf-8', sep=',')
        nver_df = pd.read_csv('beinverda.csv', encoding='utf-8', sep=',')

        #删除4个语料的nan行
        laogong_df.dropna(inplace=True)
        laopo_df.dropna(inplace=True)
        erzi_df.dropna(inplace=True)
        nver_df.dropna(inplace=True)

        #转换为 list 列表
        laogong = laogong_df.segment.values.tolist()
        laopo = laopo_df.segment.values.tolist()
        erzi = erzi_df.segment.values.tolist()
        nver = nver_df.segment.values.tolist()

    4. 预处理:分词和去停用词

        #函数preprocess_text 用于分词
        #参数content_lines为上面转换的list
        #参数sentences是空list,用来储存分词后的数据
        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 = []
        preprocess_text(laogong, sentences)
        preprocess_text(laopo, sentences)
        preprocess_text(erzi, sentences)
        preprocess_text(nver, sentences)
        random.shuffle(sentences) #将得到的数据集打散
        for sentence in sentences[:10]:
            print(sentenc)

    5. 抽取词向量特征

        #将文本中的词语转换为词频矩阵 矩阵元素a[i][j] 表示j词在i类文本下的词频
        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()
        # 将tf-idf矩阵抽取出来,元素w[i][j]表示j词在i类文本中的tf-idf权重
        weight = tfidf.toarray()
        #查看特征大小
        print ('Features length: ' + str(len(word)))

    6. TF-IDF 的中文文本 K-means 聚类

        numClass=4 #聚类分几簇
        clf = KMeans(n_clusters=numClass, max_iter=10000, init="k-means++", tol=1e-6)  #使用 k-means++ 来初始化模型,这里也可以选择随机初始化init="random"
        pca = PCA(n_components=10)  # 降维
        TnewData = pca.fit_transform(weight)  # 载入N维
        s = clf.fit(TnewData)

    7. 定义聚类结果可视化函数

    参数 result 表示聚类拟合的结果集;

    newData 表示权重 weight 降维的结果,这里需要降维到2维;

    numClass 表示聚类分为几簇

        def plot_cluster(result,newData,numClass):
            plt.figure(2)
            Lab = [[] for i in range(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(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 clf.cluster_centers_:
                try:
                    y1.append(ind1[1])
                    x1.append(ind1[0])
                except:
                    pass
            plt.plot(x1, y1, "rv") #绘制中心
            plt.show()

    8. 对数据降维到2维,然后获得结果,最后绘制聚类结果图

        pca = PCA(n_components=2)  # 输出两维
        newData = pca.fit_transform(weight)  # 载入N维
        result = list(clf.predict(TnewData))
        plot_cluster(result,newData,numClass)



    学习资料:

    《中文自然语言处理入门实战》

    相关文章

      网友评论

        本文标题:中文NLP笔记:7. 如何做中文短文本聚类

        本文链接:https://www.haomeiwen.com/subject/kicesqtx.html