知乎话题文本分词并选词后用sklearn做kmeans聚类计算

2023-12-5 12:01| 发布者: Fuller| 查看: 2604| 评论: 0

摘要: 我们使用同样的知乎二舅话题的excel,导入到Gooseeker文本分词和情感分析软件,自动分词后,进行人工选词(而不使用sklearn的自动特征选择算法),然后导出“选词匹配表”excel,对其用sklearn进行聚类分析 ... ... ...

1  背景介绍

1.1  实验目的

上个月发布了《社交媒体话题文本分词后用sklearn的kmeans算法做聚类分析》,我们将采集得到的知乎二舅话题的excel,导入到Gooseeker文本分词和情感分析软件,经自动分词后,导出“分词效果表”excel。基于自动分词的“分词效果表”,我们在python下使用sklearn库进行k-means聚类实验,并做了两个实验:

  • 实验1. 人工直接设置K值为3进行实验
  • 实验2. 使用“手肘法”人工观察拐点,取K值为7。

下图就是基于“手肘法”观察拐点并确定K值后的输出图:

在那个notebook里,我们总结指出:可视化输出的图看起来稍显杂乱,可能是数据样本本身不适合聚类,也可能是聚类算法选择不合适或者参数设置不合适,或者文档向量降维算法选择不合适等等,需要多次实验,改变设置,找到比较好的处理效果。

基于原始文本自动分词得到的结果,词的数量很大,很多词没有分析价值,除了增加处理的难度,而且会干扰分析结果的合理性,所以,通常我们要进行特征选择,可以手工选择,也可以自动选择。

今天的实验,我们使用同样的知乎二舅话题的excel,导入到Gooseeker文本分词和情感分析软件,自动分词后,进行人工选词(而不使用sklearn的自动特征选择算法),然后导出“选词匹配表”excel,对其用sklearn进行聚类分析。

手工选词的时候,可以只选名词,或者只选动词,或者选其他词性,可以分别探索和观察一下分析结果的不同。

本notebook实验内容:

  • 使用GooSeeker文本分词和情感分析软件将文本进行分词并进行人工选词,导出选词匹配数据表。人工拣选的词我们称为“打标词”。在excel表的“打标词”这一列,词与词之间使用逗号加空格作为分隔符。
  • (不再使用用sklearn的特征工程函数对选词结果进行特征选择,所以,删掉本步骤)
  • 基于手工选的特征词进行聚类分析
  • 为了在二维空间可视化,利用sklearn的降维算法,将被分析数据的维度降到2维,在二维空间展示聚类结果

1.2  实验数据来源

使用知乎_独立话题动态内容采集这个快捷采集,爬取知乎上关于二舅话题的讨论,导出excel。

1.3  实验数据预处理:中文文本分词和选词

将采集得到的知乎二舅话题的excel,导入到Gooseeker文本分词和情感分析软件,经自动分词并人工选词后,导出“选词匹配表”excel。

1.4  本notebook使用方法

基本操作顺序是:

  1. GooSeeker分词和文本分析软件上创建分析任务并导入包含原始内容的excel
  2. 在自动分词完成后进行人工选词,然后导出选词匹配表
  3. 将导出的选词匹配表放在本notebook的data/raw文件夹中
  4. 从头到尾执行本notebook的单元

注意:每个notebook项目目录都预先规划好了,具体参看Jupyter Notebook项目目录规划参考。如果要做多个分析项目,把整个模板目录专门拷贝一份给每个分析项目。

2  第三方库

本notebook使用了sklearn库做k-means算法实验。

如果未安装,请先使用下面的命令安装sklearnm库,再运行实验本notebook:

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple sklearn #国内安装使用清华的源,速度快

3  准备程序环境

导入必要的Python程序包,设定要分析的文件名变量。在这一系列notebook中,我们都使用以下变量对应GooSeeker分词结果表:

  • file_word_freq:词频表
  • file_seg_effect: 分词效果表
  • file_word_choice_matrix: 选词矩阵表
  • file_word_choice_match: 选词匹配表
  • file_word_choice_result: 选词结果表
  • file_co_word_matrix: 共词矩阵表

3.1  导入程序包并声明变量

import pandas as pd

import os

import numpy as np

from sklearn.cluster import KMeans, MiniBatchKMeans

from sklearn.decomposition import PCA

from sklearn.decomposition import TruncatedSVD

from sklearn.feature_extraction.text import TfidfVectorizer

from sklearn.feature_extraction.text import HashingVectorizer

from sklearn.feature_extraction.text import TfidfTransformer

from sklearn.pipeline import make_pipeline

from sklearn.preprocessing import Normalizer

from sklearn import metrics

from time import time

%xmode Verbose

import warnings

warnings.filterwarnings("ignore", category=DeprecationWarning)

# 存原始数据的目录

raw_data_dir = os.path.join(os.getcwd(), '..\\..\\data\\raw')

# 存处理后的数据的目录

processed_data_dir = os.path.join(os.getcwd(), '..\\..\\data\\processed')

filename_temp = pd.Series(['选词匹配'])

file_seg_effect = ''

输出结果可能如下:

Exception reporting mode: Verbose

3.2  检测data\raw目录下是否有选词匹配

以下的演示以GooSeeker分词和文本分析软件生成的选词匹配excel表为例,需要把选词匹配放到本notebook的data/raw文件夹下,如果没有数据表,下面代码执行后将提示“不存在”

# 0:'词频', 1:'分词效果', 2:'选词矩阵', 3:'选词匹配', 4:'选词结果', 5:'共词矩阵'

print(raw_data_dir + '\r\n')

for item_filename in os.listdir(raw_data_dir):

    if filename_temp[0] in item_filename:

        file_seg_effect = item_filename

        continue

if file_seg_effect:

    print("选词匹配excel表:", "data\\raw\\", file_seg_effect)

else:

    print("选词匹配excel表:不存在")

输出结果类似下面的样子:

C:\Users\work\workspace_219\notebook\知乎话题文本分词并选词后用sklearn做kmeans算法实验\notebook\eda\..\..\data\raw

选词匹配excel表: data\raw\ 选词匹配-知乎-二舅.xlsx

4  读入选词匹配并观察

4.1  读取选词匹配表

df = pd.read_excel(os.path.join(raw_data_dir, file_seg_effect))

输出结果可能会有这样的告警,不用管:

C:\ProgramData\Anaconda3\lib\site-packages\openpyxl\styles\stylesheet.py:214: UserWarning: Workbook contains no default style, apply openpyxl's default

  warn("Workbook contains no default style, apply openpyxl's default")

4.2  查看前10行数据

使用df.head()函数查看dataframe的前n行数据

df.head(10)

4.3  使用“打标词”这一列作为实验数据

“打标词”这一列是我们在文本自动分词的基础上进行人工筛选后得到的词汇,通过观察可以看到,“打标词”是在词之间插入了逗号+空格.

【注意】:本Notebook我们使用“打标词”这一列作为实验数据,利用sklearn抽取特征词。

df['打标词']

df['已分词内容'] =  df['打标词']

df['已分词内容']

4.4  去掉词与词之间的逗号,保留空格

由于后续的操作默认将空格作为词与词直接的分隔符,所以我们把“已分词内容”这一列的逗号去掉

df['已分词内容']=df['已分词内容'].str.replace(',',' ')

df['已分词内容']

4.5  去掉值为NULL的行

dropna(axis = 0, how ='any')

df = df.dropna(axis = 0, how ='any')

4.6  查看有多少篇文档

print("%d 篇文档" % len(df['已分词内容']))

输出结果如下:

767 篇文档

5  特征选择

原始数据经过分词切分以后,得到的词的数量很大,很多词没有分析价值,除了增加处理的难度,而且会干扰分析结果的合理性,所以,需要进行特征选择,可以手工选择,也可以自动选择。我们在本次实验中,利用GooSeeker分词软件的选词功能进行手工选择,以提高分析结果的合理程度。

将文档转换成文档向量(向量中每个坐标代表一个词,整个向量代表一个文档在空间中的位置和方向)的时候,我们依然使用TfidfVectorizer。其实跟上一篇《社交媒体话题文本分词后用sklearn的kmeans算法做聚类分析》不同,我们不再依靠自动的特征选择算法,而是选用了手工选特征词,那么向量化方法其实可选用的方法就更多更自由了。

每个文档都要变成一个文档向量,向量中每个词就是我们此前手工选的词。sklearn有很多生成文档向量的方法,这些方法给向量的每个元素赋值(相当于空间中的坐标值)有所不同。

  • 最简单可能是sklearn.feature_extraction.DictVectorizer,每个坐标的值只能是0或者1;
  • 进一步可以使用sklearn.feature_extraction.text.CountVectorizer,坐标值就是词频;
  • 再进一步使用feature_extraction.text.TfidfVectorizer,坐标值是IF-IDF,同时可以根据得到的tf-idf值进一步筛选掉一些数值很低的词。 我们继续使用feature_extraction.text.TfidfVectorizer,读者有兴趣的话可以使用其他的做一下对比。
  • 从df['已分词内容']字段抽取特征:仅仅利用空格作为间隔符,把选词结果切分成一个个特征词,并且统计词频和文档频率,并计算tf-idf,作为坐标值。结束时显示耗时多少及样本数量和特征数量。下面我们限定了文档频率:一方面不要文档频率过高的词,那样会引入很多没有意义的噪音词;另一方面不要文档频率过低的词,会造成过拟合而产生分析偏差。相反,实验3不修改任何参数,都用缺省参数,也是可以的,这样就表示完全赞同手工选的词,不再利用其他统计值做进一步筛选。

具体参看TfidfVectorizer的API

t0 = time()

#vectorizer = TfidfVectorizer(max_df=0.7, min_df=0.005, stop_words=None,ngram_range=(1, 2))

vectorizer = TfidfVectorizer(max_df=0.7, min_df=0.005, stop_words=None)

X = vectorizer.fit_transform(df['已分词内容'].values.astype('U'))

print("完成所耗费时间: %fs" % (time() - t0))

print("样本数量: %d, 特征数量: %d" % X.shape)

print('特征抽取完成!')

输出结果如下:

完成所耗费时间: 0.033902s

样本数量: 767, 特征数量: 135

特征抽取完成!

6  实验一:人工设置K值为3

也就是限定为只分成三类

true_k = 3 #聚类数量

6.1  对文本进行kmeans聚类

labels = df['已分词内容']

km = KMeans(n_clusters=true_k, init='k-means++', max_iter=300, n_init=5)


print("对稀疏数据(Sparse Data) 采用 %s" % km)

t0 = time()

km.fit(X)

print("完成所耗费时间:%0.3fs" % (time() - t0))

print()


print("Homogeneity值: %0.3f" % metrics.homogeneity_score(labels, km.labels_))

print("Completeness值: %0.3f" % metrics.completeness_score(labels, km.labels_))

print("V-measure值: %0.3f" % metrics.v_measure_score(labels, km.labels_))

print("Adjusted Rand-Index值: %.3f"

      % metrics.adjusted_rand_score(labels, km.labels_))

print("Silhouette Coefficient值: %0.3f"

      % metrics.silhouette_score(X, km.labels_, sample_size=1000))


print()


#用训练好的聚类模型反推文档的所属的主题类别

label_prediction = km.predict(X)   

label_prediction = list(label_prediction)

输出结果如下:

对稀疏数据(Sparse Data) 采用 KMeans(n_clusters=3, n_init=5)

完成所耗费时间:0.137s


Homogeneity值: 0.140

Completeness值: 1.000

V-measure值: 0.246

Adjusted Rand-Index值: 0.001

Silhouette Coefficient值: 0.022

6.2  输出每个簇群去重后的关键词

目的是为了观察每一类中哪些词对聚类打分有贡献,也可以根据词义了解类别代表的意义。

print("每个聚类的TOP关键词:")

order_centroids = km.cluster_centers_.argsort()[:, ::-1]


# 由于sklearn存在不同版本,这里检测后再调用get_feature_names_out或者get_feature_names

if hasattr(vectorizer,'get_feature_names_out'):

    terms = vectorizer.get_feature_names_out()

elif hasattr(vectorizer,'get_feature_names'):

    terms = vectorizer.get_feature_names()


for i in range(true_k):

    print("簇群 %d   " % (i+1), end='')

    print("该簇群所含文档占比为",'%.4f%%' % (int(label_prediction.count(i))/int(len(df['已分词内容']))))

    print("簇群关键词:")

    wordset = []

    for ind in order_centroids[i, :20]:

        wordset.append(terms[ind].replace(' ',''))

    for word in wordset:

        print(' %s ' % word, end='')

    print('\n------------------------------------------------------------------------------------------------')

输出结果如下:

6.3  可视化

6.3.1  降维

被分析的数据是高维数据,聚类结果无法直接可视化展示出来,那么,首先要将高维数据降维成2维或者3维数据。降维必然造成信息损失,到底选择哪个降维算法好,可以多尝试几个,进行对比。

我们使用TruncatedSVD将文档向量从130多维空间降维到2维空间,TruncatedSVD利用奇异值分解算法,属于主成分分析,比较适合处理我们当前使用的数据结构。但是要注意,主成分分析相当于坐标变换,得到的新的坐标不再对应到具体某个词,是组合出来的一个新的量。TruncateSVD介绍参看sklearn官网

labels=km.labels_.tolist()

#l =  km.fit_predict(X)  

svd = TruncatedSVD(n_components=2).fit(X)

datapoint = svd.transform(X)

6.3.2  使用matplotlib进行可视化画图

import matplotlib.pyplot as plt

%matplotlib inline

plt.figure(figsize=(12, 10))

label1 = [

'#FFFF00', '#008008', '#0000FF','#800080','#FFF5EE','#98FB98','#A0522D',

'#FF7F00','#FFC125','#FFFFFF','#FFFAFA','#FFF68F','#FFEFD5','#FFE4E1',

'#FFDEAD','#FFC1C1','#FFB90F','#FFA54F','#FF8C00','#C0FF3E','#FF6EB4',

'#FF4500','#FF3030','#8A2BE2','#87CEEB','#8470FF','#828282','#7EC0EE',

'#7CFC00','#7A8B8B','#79CDCD','#76EE00']

color = [label1[i] for i in labels]

plt.scatter(datapoint[:, 0], datapoint[:, 1], c=color)

centroids = km.cluster_centers_

centroidpoint = svd.transform(centroids)

plt.scatter(centroidpoint[:, 0], centroidpoint[:, 1], marker='^', s=150, c='#000000')

plt.show()

图中的黑色三角是每个簇群的中心,不同的颜色代表不同的簇群。分的界限还算清晰。

7  实验二:使用“手肘法”确定最佳的K值

7.1  执行“手肘法”

在《Jupyter Notebook使用Python做K-Means聚类分析》中,我们介绍过“手肘法”确定最佳的K的大小:通过观察明显的拐点来确定最佳的K值。 我们在此也实验下:

import matplotlib.pyplot as plt

%matplotlib inline

plt.rcParams['font.sans-serif'] = ['SimHei']

plt.rcParams['axes.unicode_minus'] = False

n_clusters= 10

wcss = []

for i in range(1,n_clusters):

    km = KMeans(n_clusters=i, init='k-means++', max_iter=300, n_init=2)

    km.fit(X)

    wcss.append(km.inertia_)

plt.plot(range(1,n_clusters),wcss)

plt.title('肘 部 方 法')

plt.xlabel('聚类的数量')

plt.ylabel('wcss')

plt.show()

手肘法是一个经验方法,而且肉眼观察也因人而异,特别是遇到模棱两可的时候。从上面的图来看,似乎没有一个明显的“肘部”。我们人为指定K值为6

# 把人工观察手肘法图的拐点作为K值

true_k = 6 #聚类数量

7.2  对文本进行kmeans聚类

labels = df['已分词内容']

km = KMeans(n_clusters=true_k, init='k-means++', max_iter=300, n_init=5)

print("对稀疏数据(Sparse Data) 采用 %s" % km)

t0 = time()

km.fit(X)

print("完成所耗费时间:%0.3fs" % (time() - t0))

print()

print("Homogeneity值: %0.3f" % metrics.homogeneity_score(labels, km.labels_))

print("Completeness值: %0.3f" % metrics.completeness_score(labels, km.labels_))

print("V-measure值: %0.3f" % metrics.v_measure_score(labels, km.labels_))

print("Adjusted Rand-Index值: %.3f"

      % metrics.adjusted_rand_score(labels, km.labels_))

print("Silhouette Coefficient值: %0.3f"

      % metrics.silhouette_score(X, km.labels_, sample_size=1000))

print()

#用训练好的聚类模型反推文档的所属的主题类别

label_prediction = km.predict(X)   

label_prediction = list(label_prediction)

输出结果如下:

对稀疏数据(Sparse Data) 采用 KMeans(n_clusters=6, n_init=5)

完成所耗费时间:0.384s


Homogeneity值: 0.244

Completeness值: 1.000

V-measure值: 0.393

Adjusted Rand-Index值: 0.002

Silhouette Coefficient值: 0.032

7.3  输出每个簇群去重后的关键词

print("每个聚类的TOP关键词:")

order_centroids = km.cluster_centers_.argsort()[:, ::-1]

# 由于sklearn存在不同版本,这里检测后再调用get_feature_names_out或者get_feature_names

if hasattr(vectorizer,'get_feature_names_out'):

    terms = vectorizer.get_feature_names_out()

elif hasattr(vectorizer,'get_feature_names'):

    terms = vectorizer.get_feature_names()

for i in range(true_k):

    print("簇群 %d   " % (i+1), end='')

    print("该簇群所含文档占比为",'%.4f%%' % (int(label_prediction.count(i))/int(len(df['已分词内容']))))

    print("簇群关键词:")

    wordset = []

    for ind in order_centroids[i, :20]:

        wordset.append(terms[ind].replace(' ',''))

    for word in wordset:

        print(' %s ' % word, end='')

    print('\n------------------------------------------------------------------------------------------------')

7.4  可视化

7.4.1  降维

labels=km.labels_.tolist()

#l =  km.fit_predict(X)  

svd = TruncatedSVD(n_components=2).fit(X)

datapoint = svd.transform(X)

7.4.2  使用matplotlib进行可视化画图

import matplotlib.pyplot as plt

%matplotlib inline

plt.figure(figsize=(12, 10))

label1 = [

'#FFFF00', '#008008', '#0000FF','#800080','#FFF5EE','#98FB98','#A0522D',

'#FF7F00','#FFC125','#FFFFFF','#FFFAFA','#FFF68F','#FFEFD5','#FFE4E1',

'#FFDEAD','#FFC1C1','#FFB90F','#FFA54F','#FF8C00','#C0FF3E','#FF6EB4',

'#FF4500','#FF3030','#8A2BE2','#87CEEB','#8470FF','#828282','#7EC0EE',

'#7CFC00','#7A8B8B','#79CDCD','#76EE00']

color = [label1[i] for i in labels]

plt.scatter(datapoint[:, 0], datapoint[:, 1], c=color)

centroids = km.cluster_centers_

centroidpoint = svd.transform(centroids)

plt.scatter(centroidpoint[:, 0], centroidpoint[:, 1], marker='^', s=150, c='#000000')

plt.show()

图中的黑色三角是每个簇群的中心,不同的颜色代表不同的簇群。

8  实验三

该数据集只有700多条数据,选词太多的话,有些词出现的频率会太低。这个实验我们采取一个策略:

  • 只选名词(也可以只选其他词性的词,他们会体现不同的分析角度)
  • 观察词频和文频(该词出现在多少文档中),剔除掉低频词
  • 不选“二舅”这个词,因为所有文本都是跟这个主题有关

8.1  加载选词匹配表

将选词匹配excel表加载到DataFrame中。

这次实验的所有程序代码的变量名都加一个后缀_hf,表示这次实验“高频词”,以便与前面的实验不冲突。

file_seg_effect_hf = os.path.join(os.getcwd(), '../../data/raw/高频名词.xlsx')

df_hf = pd.read_excel(file_seg_effect_hf)

df_hf.head(10)

8.2  简单清洗数据

在df中创建一个新列,替换掉选词结果中的逗号,滤除掉空数据,以便进一步转换成文档向量。

df_hf['已分词内容']=df_hf['打标词'].str.replace(',',' ').dropna(axis = 0, how ='any')

df_hf['已分词内容']

8.3  转换成文档向量

t0_hf = time()

vectorizer_hf = TfidfVectorizer()

X_hf = vectorizer_hf.fit_transform(df_hf['已分词内容'].values.astype('U'))

print("完成所耗费时间: %fs" % (time() - t0_hf))

print("样本数量: %d, 特征数量: %d" % X_hf.shape)

print('特征抽取完成!')

输出结果如下:

完成所耗费时间: 0.024976s

样本数量: 687, 特征数量: 100

特征抽取完成!

8.4  聚类成3类

labels_hf = df_hf['已分词内容']

km_hf = KMeans(n_clusters=3, init='k-means++', max_iter=300, n_init=5)

print("对稀疏数据(Sparse Data) 采用 %s" % km_hf)

t0_hf = time()

km_hf.fit(X_hf)

print("完成所耗费时间:%0.3fs" % (time() - t0_hf))

print()

print("Homogeneity值: %0.3f" % metrics.homogeneity_score(labels_hf, km_hf.labels_))

print("Completeness值: %0.3f" % metrics.completeness_score(labels_hf, km_hf.labels_))

print("V-measure值: %0.3f" % metrics.v_measure_score(labels_hf, km_hf.labels_))

print("Adjusted Rand-Index值: %.3f"

      % metrics.adjusted_rand_score(labels_hf, km_hf.labels_))

print("Silhouette Coefficient值: %0.3f"

      % metrics.silhouette_score(X_hf, km_hf.labels_, sample_size=1000))

print()

#用训练好的聚类模型反推文档的所属的主题类别

label_prediction_hf = km_hf.predict(X_hf)   

label_prediction_hf = list(label_prediction_hf)

输出结果如下:

对稀疏数据(Sparse Data) 采用 KMeans(n_clusters=3, n_init=5)

完成所耗费时间:0.188s


Homogeneity值: 0.111

Completeness值: 1.000

V-measure值: 0.200

Adjusted Rand-Index值: 0.001

Silhouette Coefficient值: 0.032

8.5  输出每个簇群去重后的关键词

目的是为了观察每一类中哪些词对聚类打分有贡献,也可以根据词义了解类别代表的意义。

print("每个聚类的TOP关键词:")

order_centroids_hf = km_hf.cluster_centers_.argsort()[:, ::-1]

# 由于sklearn存在不同版本,这里检测后再调用get_feature_names_out或者get_feature_names

if hasattr(vectorizer_hf,'get_feature_names_out'):

    terms_hf = vectorizer_hf.get_feature_names_out()

elif hasattr(vectorizer_hf,'get_feature_names'):

    terms_hf = vectorizer_hf.get_feature_names()

for i in range(3):

    print("簇群 %d   " % (i+1), end='')

    print("该簇群所含文档占比为",'%.4f%%' % (int(label_prediction_hf.count(i))/int(len(df_hf['已分词内容']))))

    print("簇群关键词:")

    wordset = []

    for ind in order_centroids_hf[i, :20]:

        wordset.append(terms_hf[ind].replace(' ',''))

    for word in wordset:

        print(' %s ' % word, end='')

    print('\n------------------------------------------------------------------------------------------------')

8.6  可视化

import matplotlib.pyplot as plt

%matplotlib inline

# 用svd(奇异值分解)方法降维,也就是把维度下降到2个主成分上。

labels_hf = km_hf.labels_.tolist()

#print(labels_hf)

#l =  km.fit_predict(X)  

svd_hf = TruncatedSVD(n_components=2).fit(X_hf)

datapoint_hf = svd_hf.transform(X_hf)

plt.figure(figsize=(12, 10))

label1 = [

'#FFFF00', '#008008', '#0000FF','#800080','#FFF5EE','#98FB98','#A0522D',

'#FF7F00','#FFC125','#FFFFFF','#FFFAFA','#FFF68F','#FFEFD5','#FFE4E1',

'#FFDEAD','#FFC1C1','#FFB90F','#FFA54F','#FF8C00','#C0FF3E','#FF6EB4',

'#FF4500','#FF3030','#8A2BE2','#87CEEB','#8470FF','#828282','#7EC0EE',

'#7CFC00','#7A8B8B','#79CDCD','#76EE00']

# 给每个数据点上色

color_hf = [label1[i] for i in labels_hf]

plt.scatter(datapoint_hf[:, 0], datapoint_hf[:, 1], c=color_hf)

# 画中心点

centroids_hf = km_hf.cluster_centers_

centroidpoint_hf = svd_hf.transform(centroids_hf)

plt.scatter(centroidpoint_hf[:, 0], centroidpoint_hf[:, 1], marker='^', s=150, c='#000000')

plt.show()

9  总结

本Notebook使用Gooseeker文本分词和情感分析软件导出的选词匹配excel表格,在python下使用sklearn库进行k-means聚类,实验有3个:

  • 实验1. 人工直接设置K值为3进行实验
  • 实验2. 使用“手肘法”人工观察拐点,取K值为6
  • 实验3. 利用GooSeeker分词和情感分析软件手工选词可以选择某种词性的功能,只选择高频名词。

对于可视化输出的图,可能不同实验者会有不同的解读。总的来说,解读聚类结果是比较难的,因为一个文档被向量化以后变成了一个高位空间的向量,高维空间是不能直观解读的。我们只能看这么多维度中贡献最大的维度是什么,根据维度代表的词,猜测是什么含义。

但是,使用GooSeeker分词和情感分析软件的手工选词功能,作用是十分明显的,通过人脑判断,特征选择是最准确的。下面分别截图对比一下两者的区别(注意,聚类计算的时候,每次结果会有稍许变化,本notebook上面的计算过程得到的图会跟下面这个历史截图不一样)。第一张图是自动特征选择的结果;第二张图是手工选词的结果。


上图对比可见,手工选词效果提升很大。

即便这样,在自动聚类计算之后的结果解读仍然是一个很大的挑战,需要阅读已经标记了类别的文本内容,理解每一类代表了什么。

另外,由于知乎回答有长有短,而且差距极大,针对每个回答这种粒度做分析和比较,不是很合适,可以考虑段落级分析,也许还可以更细到句子级,这要看分析目的是怎样的,可能参考一些内容分析和质性研究的方法是有益的。

后续我们会使用不同数据源的数据(比如:微博,知乎,新闻等),使用sklearn进行多种算法的实验,在实验中总结和改进。

10. 源代码下载

下载notebook源代码请进入:对分词并选词后的社交媒体话题文本用sklearn的kmeans做聚类分析

1

鲜花

握手

雷人

路过

鸡蛋

刚表态过的朋友 (1 人)

最新评论

GMT+8, 2024-12-4 20:50