数据聚类与分群分析

本文代码及数据集来自《Python大数据分析与机器学习商业案例实战》

KMeans算法

KMeans算法名称中的K代表类别数量,Means代表每个类别内样本的均值,所以KMeans算法又称为K-均值算法。KMeans算法以距离作为样本间相似度的度量标准,将距离相近的样本分配至同一个类别。样本间距离的计算方式可以是欧氏距离、曼哈顿距离、余弦相似度等,KMeans算法通常采用欧氏距离来度量各样本间的距离。
数据聚类与分群分析

# 1.读取数据
import pandas as pd
data = pd.read_excel('客户信息.xlsx')
data.head()

# 2.可视化展示
import matplotlib.pyplot as plt
plt.scatter(data.iloc[:, 0], data.iloc[:, 1], c="green", marker='*')
plt.xlabel('age') 
plt.ylabel('salary')
plt.show()

# 3.数据建模
from sklearn.cluster import KMeans
kms = KMeans(n_clusters=3, random_state=123)
kms.fit(data)
label = kms.labels_
label = kms.fit_predict(data)
print(label)

# 4.建模效果可视化展示
plt.scatter(data[label == 0].iloc[:, 0], data[label == 0].iloc[:, 1], c="red", marker='o', label='class0')
plt.scatter(data[label == 1].iloc[:, 0], data[label == 1].iloc[:, 1], c="green", marker='*', label='class1')
plt.scatter(data[label == 2].iloc[:, 0], data[label == 2].iloc[:, 1], c="blue", marker='+', label='class2')
plt.xlabel('age')
plt.ylabel('salary')
plt.legend()

# 5.补充知识点,查看各标签人的收入均值
print(data[label == 0].iloc[:, 1].mean())
print(data[label == 1].iloc[:, 1].mean())
print(data[label == 2].iloc[:, 1].mean())

运行结果:
数据聚类与分群分析

DBSCAN算法

DBSCAN(全称为Density-Based Spatial Clustering of Applications withNoise)是一种以密度为基础的空间聚类算法,可以用密度的概念剔除不属于任一类别的噪声点。该算法将簇定义为密度相连的点的最大集合,将具有足够密度的区域划分为簇,并可以发现任意形状的簇。
数据聚类与分群分析
KMeans算法与DBSCAN算法的区别:

# DBSCAN算法的代码实现
# 1.读取数据
import pandas as pd
data = pd.read_excel('演示数据.xlsx')
data.head()

# 2.数据可视化
import matplotlib.pyplot as plt
plt.scatter(data.iloc[:, 0], data.iloc[:, 1], c="green", marker='*')
plt.xlabel('x')
plt.ylabel('y')
plt.show()

# 3.数据建模
from sklearn.cluster import DBSCAN
dbs = DBSCAN()
dbs.fit(data)
label_dbs = dbs.labels_

# 4.查看聚类结果
print(label_dbs)

# 5.用散点图展示DBSCAN算法的聚类结果
plt.scatter(data[label_dbs == 0].iloc[:, 0], data[label_dbs == 0].iloc[:, 1], c="red", marker='o', label='class0')
plt.scatter(data[label_dbs == 1].iloc[:, 0], data[label_dbs == 1].iloc[:, 1], c="green", marker='*', label='class1')
plt.xlabel('x')
plt.ylabel('y')
plt.legend()

# KMeans VS DBSCAN
from sklearn.cluster import KMeans
KMs = KMeans(n_clusters=2)
KMs.fit(data)
label_kms = KMs.labels_
print(label_kms)

plt.scatter(data[label_kms == 0].iloc[:, 0], data[label_kms == 0].iloc[:, 1], c="red", marker='o', label='class0')
plt.scatter(data[label_kms == 1].iloc[:, 0], data[label_kms == 1].iloc[:, 1], c="green", marker='*', label='class1')
plt.xlabel('x')
plt.ylabel('y')
plt.legend()

运行结果:
数据聚类与分群分析
可以看到,对于形状类似同心圆的数据,KMeans算法的聚类效果较差,只能机械地将数据分为左右两部分,而无法区分外圆和内圆。
数据聚类与分群分析

案例实战:新闻聚类分群模型

# 案例实战 - 新闻聚类分群模型
# 文本数据的读取与处理
# # 1.读取数据
import pandas as pd
df = pd.read_excel('新闻.xlsx')
print(df.head())

print(df.shape) #(962, 5)

运行结果:
数据聚类与分群分析

# # 2.中文分词
import jieba
words = []
for i, row in df.iterrows(): # i对应每一行的行号,row对应每一行的内容
    word = jieba.cut(row['标题'])
    result = ' '.join(word) 
    words.append(result)
print(words[0:3])
'''
import jieba
words = []
for i, row in df.iterrows():
    words.append(' '.join(jieba.cut(row['标题'])))
print(words[0:3])
'''

运行结果:[‘信托公司 2019 年 上半年 经营 业绩 概览’, ‘首单 信托 型 企业 ABS 获批’, ‘华能 贵 诚信 托孙磊 : 金融 科技 助力 打造 开放 信托 生态’]

# # 3.文字转数字:通过建立词频矩阵构造特征变量
# 将之前所有的新闻标题进行文本向量化,从而构造特征变量
from sklearn.feature_extraction.text import CountVectorizer
vect = CountVectorizer()
X = vect.fit_transform(words) # 文本向量化转换
X = X.toarray() # 转为数组

words_bag = vect.vocabulary_
print(words_bag) # 查看词袋

words_bag2 = vect.get_feature_names()  # 只想看到词,不想看到编号
import pandas as pd
df = pd.DataFrame(X, columns=words_bag2)
print(df.head())

运行结果:
数据聚类与分群分析
数据聚类与分群分析

# 模型搭建与使用
# # 1.通过KMeans算法进行聚类分群
from sklearn.cluster import KMeans
kms = KMeans(n_clusters=10, random_state=123)
k_data = kms.fit_predict(df)
print(k_data)

import numpy as np
words_ary = np.array(words)
print(words_ary[k_data == 1])  # 可以把数字1改成其他数字看看效果

运行结果:
数据聚类与分群分析
可以看到,分类为1的新闻标题大多是和Python相关的。

# # 2.通过DBSCAN算法进行聚类分群
from sklearn.cluster import DBSCAN
dbs = DBSCAN(eps=1, min_samples=3)
d_data = dbs.fit_predict(df)
print(d_data)

运行结果:
数据聚类与分群分析
从图中可以看出,DBSCAN算法对新闻标题的聚类效果较差,其中有大量离群点(-1),即不知道这条新闻标题属于什么分类。这是因为在13.3.2小节进行文本向量化后,每个新闻标题都有3401个特征,过多的特征容易导致样本点间的距离较远,从而产生离群点。这也说明了对于特征变量较多的数据,KMeans算法的聚类效果要优于DBSCAN算法的聚类效果。

# 模型优化(用余弦相似度代替欧氏距离)
from sklearn.metrics.pairwise import cosine_similarity
cosine_similarities  = cosine_similarity(df)
print(cosine_similarities)

from sklearn.cluster import KMeans
kms = KMeans(n_clusters=10, random_state=123)
k_data = kms.fit_predict(cosine_similarities) # 对余弦相似度的计算结果进行聚类分群
print(k_data)
print(k_data == 3)

运行结果:
数据聚类与分群分析
数据聚类与分群分析

print(words[0:3])
words_ary = np.array(words)
print(words_ary[0:3])

import numpy as np
words_ary = np.array(words)
print(words_ary[k_data == 3])  # 可以把数字3改成其他数字看看效果

运行结果:
数据聚类与分群分析

jieba库的使用

# 1.jieba库的简单演示
import jieba
word = jieba.cut('我爱北京*')
for i in word:
    print(i)
    
# 2.读取文本内容
import jieba
report = open('信托行业年度报告.txt', 'r').read()
words = jieba.cut(report)

# 3.按指定长度提词
report_words = []
for word in words:  # 将大于4个字的词语放入列表
    if len(word) >= 4:
        report_words.append(word)
print(report_words)

# 4.统计高频词汇的词频
from collections import Counter
result = Counter(report_words).most_common(50)  # 取最多的50组
print(result)

需要注意的是,用cut()函数分词得到的word不是一个列表,而是一个迭代器。所谓迭代器其实和列表很相似,可以把它理解成一个“隐身的列表”。但是迭代器里的元素要通过for循环来访问,所以第3~4行代码不能改写成print(word)。

上一篇:社区发现算法——LPA与SLPA算法


下一篇:PyQt5基础学习-QCalendarWidget(日历控件) 1.QCalendarWidget().setMinimumData(设置最小范围) 2. QCalendarWidget().setM