聚类分析,是一个无监督学习里面非常重要的课题,无论是在风控还是在其他业务中,通过对大规模的数据分析,找出里面的聚类关系,有助于发现新的问题或者重点问题,我们可以通过对评论文本的分析,我们可以发现消费者关注的产品或服务痛点;通过对来电语音转文本聚类,可以知道公司售后业务的典型问题或者新问题的爆发;通过对昵称聚类,可以发现批量注册用户团伙,通过评论聚类,发现某个商家的核心问题是啥;我们先讲理论,在通过一个文本的案例解释该算法的过程。
伽韦 sx111505 珂视频箹pz
每天 8粒,7天做真男人
每天 6粒,4天做真男人
...
每天 8粒,3天做真男人
风险评论
菜品不新鲜,吃了拉肚子
文本聚类方法非常多,我们今天讨论DBSCAN,也是一个非常经典的算法,我们上期讲过的算法,本文本进行简短的回顾,并用一个评价数据的聚类,来进行实战应用,下面就是发现的一个簇的文本。
一、算法概述
二、 基本概念
1、1个核心思想
2、2个算法参数,邻域半径R、最少点数目MinPoints
3、3种点的类别,核心点、边界点、噪声点
噪声点:对于非核心点的样本n,若n不在任意核心点p的-领域内,那么样本n称为噪声点。
4、4种点的关系,密度直达、密度可达、密度相连、非密度相连。
三、算法思想
1、寻找核心点形成临时聚类簇
2、合并临时聚类簇得到聚类簇
四、sklearn算法介绍
1、基本用法
sklearn.cluster.DBSCAN(eps=0.5, *,
min_samples=5,
metric='euclidean',
metric_params=None,
algorithm='auto',
leaf_size=30,
p=None,
n_jobs=None
)
2、核心参数
eps: float,ϵ-邻域的距离阈值 min_samples:int,样本点要成为核心对象所需要的 ϵ-邻域的样本数阈值
3、其他参数
metric:度量方式,默认为欧式距离,可以使用的距离度量参数有:
欧式距离 “euclidean” 曼哈顿距离 “manhattan” 切比雪夫距离“chebyshev” 闵可夫斯基距离 “minkowski” 带权重闵可夫斯基距离 “wminkowski” 标准化欧式距离 “seuclidean” 马氏距离“mahalanobis” 自己定义距离函数
algorithm:近邻算法求解方式,有四种:
“brute”蛮力实现 “kd_tree” KD树实现 “ball_tree”球树实现 “auto”上面三种算法中做权衡,选择一个拟合最好的最优算法。
leaf_size:使用“ball_tree”或“kd_tree”时,停止建子树的叶子节点数量的阈值 p:只用于闵可夫斯基距离和带权重闵可夫斯基距离中p值的选择,p=1为曼哈顿距离, p=2为欧式距离。如果使用默认的欧式距离不需要管这个参数。 n_jobs:CPU并行数,若值为 -1,则用所有的CPU进行运算
4、属性
core_sample_indices_: 核心点的索引,因为labels_不能区分核心点还是边界点,所以需要用这个索引确定核心点 components_:训练样本的核心点 labels_:每个点所属集群的标签,也就是聚类的编号,-1代表噪声点
5、算法案例
from sklearn.cluster import DBSCAN
import numpy as np
X = np.array([[1, 2], [2, 2], [2, 3],
[8, 7], [8, 8], [25, 80]])
clustering = DBSCAN(eps=3, min_samples=2).fit(X)
clustering.labels_
array([ 0, 0, 0, 1, 1, -1])
-1:最后一个为异常点,不属于任何一个群
五、文本聚类实战
1、基础数据的读取
# 加载所需要的包
from sklearn.feature_extraction.text import TfidfVectorizer
import pandas as pd
import os
import jieba
# 设置工作空间 & 读取数据
os.chdir('/Users/wuzhengxiang/Documents/DataSets/评价数据')
train = pd.read_csv('train.csv',sep='\t')
# 查看数据大小和形状
train.shape
2)
# 查看下前10条数据
train.head(10)
:
label comment
0 0 一如既往地好吃,希望可以开到其他城市
1 0 味道很不错,分量足,客人很多,满意
2 0 下雨天来的,没有想象中那么火爆。环境非常干净,古色古香的,我自己也是个做服务行业的,我都觉得...
3 0 真心不好吃 基本上没得好多味道
4 0 少送一个牛肉汉堡 而且也不好吃 特别是鸡肉卷 **都不想评论了 谁买谁知道
5 0 用美团,图打折。
6 0 好难吃水煮鸡杂呀
7 0 环境很好,服务很热情,味道非常好,鱼也很新鲜,我和儿子吃的好饱,包子和饺子很好吃哟,
8 0 一如既往的好吃,个人更喜欢吃全翅
9 0 四个就把我吃饱了……阔以
2、文本向量化
#进行分字处理 用结巴分词
data = train['comment'].apply(lambda x:' '.join(jieba.lcut(x)) )
# 看看前几条分词的结果
for i in data.head():
print(i)
一如既往 地 好吃 , 希望 可以 开 到 其他 城市
味道 很 不错 , 分量 足 , 客人 很多 , 满意
下雨天 来 的 , 没有 想象 中 那么 火爆 。环境 非常 干净 , 古色古香 的 , 我 自己 也 是 个 做 服务行业 的 , 我 都 觉得 他们 的 服务 非常 好 , 场地 脏 了 马上 就 有 阿姨 打扫 。
真心 不 好吃 基本上 没 得 好多 味道
少送 一个 牛肉 汉堡 而且 也 不 好吃 特别 是 鸡肉 卷 * * 都 不想 评论 了 谁 买 谁 知道
# 进行向量转化
vectorizer_word = TfidfVectorizer(max_features=800000,
token_pattern=r"(?u)\b\w+\b",
min_df = 5,
#max_df=0.1,
analyzer='word',
ngram_range=(1,2)
)
vectorizer_word = vectorizer_word.fit(data)
tfidf_matrix = vectorizer_word.transform(data)
#查看词典的大小
len(vectorizer_word.vocabulary_)
6968
#查看词典里面的词-部分词语
vectorizer_word.vocabulary_
{...
'骗人 的': 6878,
'的 可能': 4971,
'我点 了': 3629,
'煮 了': 4706,
'了 只有': 886,
'一个 人': 92,
'人 都': 1078,
'不够 吃': 378,
'点餐 的': 4648,
'的 朋友': 5068,
'他们 家': 1134,
'蛋炒饭': 5878,
'银耳汤': 6677,
'好吃 实惠': 2725,
'里面 还有': 6645,
'还有 免费': 6328,
'免费 的': 1371,
...}
3、DBSCAN训练
# 设置下最大可展示的行
1000)
# 进行模型训练
from sklearn.cluster import DBSCAN
clustering = DBSCAN(eps=0.95, min_samples=5).fit(tfidf_matrix)
# 我们看看分了所少个群,每个群的样本数是多少
len(pd.Series(clustering.labels_).value_counts())
42
pd.Series(clustering.labels_).value_counts()
9008
0 631
5 28
8 27
6 23
14 19
7 16
...
28 10
1 10
12 10
3 9
29 8
4、聚类结果分析
# 分群标签打进原来的数据
train['labels_'] = clustering.labels_
# 抽取编号为5的群看看 可以看到,这个群都是吃拉肚子的反馈,聚类效果还是非常可以的
for i in train[train['labels_']==5]['comment']:
print(i)
吃了拉肚子。一点当地重庆味道都没有
吃了拉肚子 弄得不卫生
吃了拉肚子 特别不卫生
吃了拉肚子,确实卫生不好
我吃了拉肚子mmp
吃了拉肚子
不干净,吃了拉肚子,还发烧了
老样子,吃了拉肚子
鱼不新鲜,吃了拉肚子……
吃了拉肚子,一上午都在医院
好像拉肚子了拉肚子
太辣,吃了拉肚子
吃了拉肚子,现在都十二点多了,还疼的睡不着。
我吃了拉肚子……
吃了拉肚子。不是正宗湖北油闷味道。。。
不新鲜,吃了拉肚子
泡椒猪肝吃了拉肚子
吃了拉肚子,快要拉死人了。
好像不卫生吃了拉肚子,口感不好。
味道不行 吃了拉肚子
别买 不卫生吃了拉肚子
菜品不新鲜,吃了拉肚子
鸭脚变味了,吃了拉肚子
吃了拉肚子 有点不新鲜了
就是不知道怎么回事我吃了拉肚子
吃了拉肚子,味道怪怪的
吃了拉肚子!拉肚子!
吃了拉肚子,真蛋疼
# 抽取编号为5的群看看 可以看到,这个群都是好评的
for i in train[train['labels_']==5]['comment']:
print(i)
上菜快,味道不错
环境还不错,上菜速度快,服务态度好
环境好,上菜速度快,味道特别好吃,去吃了很多次了
菜品很不错,上菜速度快,环境不错
便宜,味道好,上菜快,环境好,
菜品丰富不错,环境好,上菜速度快。
还不错,上菜速度快,口味也合适,可以试一试,经常去
味道好 上菜速度快 环境也不错
口味不错,上菜速度快,推荐品尝
菜品新鲜,味道不错,上菜速度快。
经常去,味道不错,上菜速度快。
服务很好,上菜速度快。味道不错。
环境很好,上菜速度快。下次还来。
很好,速度快,环境也不错,,,
train['labels_'] = clustering.labels_
for i in train[train['labels_']==14]['comment']:
print(i)
排骨汤都是臭的。
难吃,肉是臭的!!!!!!!
肉是臭的还卖无语了
海南小台农芒 500g 打开一个居然是臭的
肉是臭的,吃得一嘴恶心!
为什么我总感觉肉是臭的 拿给狗狗吃了 不敢吃
难吃,牛肉是臭的
nbsp;卤蛋是臭的!!!!
肉是臭的,失望透顶
今天的肉是臭的,不好吃鱼香肉丝木桶饭#
肉是臭的就算了,平菇也是臭的,以后不会再点了
肉是臭的 就这样做生意?
肉是坏的,不好吃
肉是臭的,我吃了一口,全吐了
难吃 肉是臭的。
鸡肉竟然是臭的!!!!
肉是臭的。不好吃。
味道还可以!但是!鸡肉居然是臭的!是臭的!
猪脚都是臭的。
train['labels_'] = clustering.labels_
for i in train[train['labels_']==16]['comment']:
print(i)
饭里面居然有钢丝球的钢丝
肉里面居然有钢丝球的钢丝……太恶心了
要吃死人嘛,都有钢丝球。
凉糕里面居然都有钢丝球
里面有钢丝球丝丝。#小炒肉#
train['labels_'] = clustering.labels_
for i in train[train['labels_']==22]['comment']:
print(i)
不错,经常来的,吃了N次了,爽歪歪
它家团了N次,味道好,服务态度也好
去吃了n次了真心不错,和姐妹聚餐可以
去了很多很多次了,一如既往的好,,希望再多一点菜品!!
味道好,服务也好,吃了N次了。
去了N次了。一如既往的好。加油
吃了N次了,一如既往的好吃,辣得过瘾,肉肉好多哟,味道好吃
··· END ···