Python数据聚类与分群分析【附代码】
KMeans算法的K代表类别数量,Means代表每个类别内样本的均值,所以KMeans算法又称为K-均值算法。KMeans算法以距离作为样本间相似度的度量标准,将距离相近的样本分配至同一个类别。样本间距离的计算方式可以是欧氏距离,曼哈顿距离,余弦相似度等,KMeans算法通常采用欧氏距离来度量各样本间的距离。KMeans算法的核心思想是。
目录
1、KMeans算法
(1)KMeans算法的原理介绍
KMeans算法的K代表类别数量,Means代表每个类别内样本的均值,所以KMeans算法又称为K-均值算法。KMeans算法以距离作为样本间相似度的度量标准,将距离相近的样本分配至同一个类别。样本间距离的计算方式可以是欧氏距离,曼哈顿距离,余弦相似度等,KMeans算法通常采用欧氏距离来度量各样本间的距离。
KMeans算法的核心思想是:对每个样本点计算离各个中心点的距离,并将该样本点分配给最近中心点代表的类别,一次迭代完成后,根据聚类结果更新每个类别的中心点,然后重复之前操作再次迭代,直到前后两次分类结果没有差别。下面我们以一个简单案例对KMeans算法的原理进行解释,该案例目的是将样本点聚成3个类别(K=3)
(2)KMeans算法的代码实现
使用一些简单的二维数据来说明如何在Python当中实现KMeans算法:
import numpy as np
data = np.array([[3, 2], [4, 1], [3, 6], [4, 7], [3, 9], [6, 8], [6, 6], [7, 7]])
import matplotlib.pyplot as plt
plt.scatter(data[:, 0], data[:, 1], c="red", marker='o', label='samples')
plt.legend()
plt.show()
data[:,0]表示的则是X列的数,同理data[:, 1]表示的则是Y列的数。此外散点图函数scatter()中的参数c表示颜色,maker表示形状,label则表示数据标签,散点图如下所示:
调用Python已经开发好的相关库来进行KMeans的聚类运算,代码如下:
from sklearn.cluster import KMeans
kms = KMeans(n_clusters=2)
kms.fit(data)
使用散点图展示KMeans算法的聚类结果:
plt.scatter(data[label == 0][:, 0], data[label == 0][:, 1], c="red", marker='o', label='class0')
plt.scatter(data[label == 1][:, 0], data[label == 1][:, 1], c="green", marker='*', label='class1')
plt.legend()
使用散点图展示KMeans算法的聚类结果:
我们将K值设为3 :
kms_3 = KMeans(n_clusters=3)
kms_3.fit(data)
label_3 = kms_3.labels_
print(label_3)
plt.scatter(data[label_3 == 0][:, 0], data[label_3 == 0][:, 1], c="red", marker='o', label='class0')
plt.scatter(data[label_3 == 1][:, 0], data[label_3 == 1][:, 1], c="green", marker='*', label='class1')
plt.scatter(data[label_3 == 2][:, 0], data[label_3 == 2][:, 1], c="blue", marker='+', label='class2')
plt.legend()
散点图如下所示:
(3)案例 - 银行客户分群模型
1、背景
银行通常拥有海量的客户,对于不同的客户,银行需要进行不同的营销与工作开展策略,例如对于高收入且风险承受能力强的客户,可以进行重点挖掘业务机会,例如可以给他推销一些收益率高但周期相对较长的理财产品;而对于低收入且风险承受能力较弱的客户,则需要制定不同的营销与工作策略。因此对于银行来说,通常需要将客户进行分群处理,对于不同分群的客户进行不同的处理。
2、读取银行客户数据
读取数据和创建散点图代码如下:
import pandas as pd
data = pd.read_excel('客户信息.xlsx')
data.head()
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)
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()
2、DBSCAN算法
DBSCAN (Density-Based Spatial Clustering of Applications with Noise)是一种以密度为基础的空间聚类算法,可以用密度的概念剔除不属于任意类别的噪声点。该算法将簇定义为密度相连的点的最大集合,将具有足够密度的区域划分为簇,并可以发现任意形状的簇。
(1)DBSCAN算法的原理介绍
下面我们以一个简单案例对DBSCAN算法的原理进行解释,我们设定画圆半径为1,圆内最小样本点数为3:
(2)DBSCAN算法的代码实现
演示完DBSCAN算法的原理之后,我们先看两张KMeans与DBSCAN聚类的对比图片:
创建KMeans与DBSCAN散点图,首先让我们创建原始的散点图:
import pandas as pd
data = pd.read_excel('演示数据.xlsx')
data.head()
import matplotlib.pyplot as plt
plt.scatter(data.iloc[:, 0], data.iloc[:, 1], c="green", marker='*')
plt.xlabel('x')
plt.ylabel('y')
plt.show()
原始的散点图:
创建DBSCAN散点图:
from sklearn.cluster import DBSCAN
dbs = DBSCAN()
dbs.fit(data)
label_dbs = dbs.labels_
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()
(3)KMeans VS DBSCAN
创建KMeans散点图:
from sklearn.cluster import KMeans
KMs = KMeans(n_clusters=2)
KMs.fit(data)
label_kms = KMs.labels_
10]
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算法聚类效果较差,只能机械地将数据分为左右两部分,而无法以外圆内圆的方式进行区分。
3、案例 - 新闻聚类分群模型
(1)背景
新闻种类繁复多样,可以分为军事,政治,娱乐,财经,体育,科技,历史等等题材,我们需要将每条新闻划分成合适的类别,匹配到正确的版面,以便读者阅读,因此新闻的聚类分群显得十分重要。
(2)文本数据的读取与处理
1、读取数据
import pandas as pd
df = pd.read_excel('新闻.xlsx')
df.head()
df.head()用来展示前五行数据。运行结果如下图所示:
2、中文分词
本节中的新闻标题文本,而Python是不能直接处理这种文本数据的,我们需要将其进行数值转换。需要利用到的两个核心技术为:中文分词和文本向量化。中文分词:所谓中文分词就是将一句话拆分成一些词语,例如“我爱北京天安门”就可以拆分成“我”、“爱”、“北京”、“天安门”。中文分词后就可以进行文本向量化,搭建词频矩阵从而将文字转为数字了。Python有专门处理中文分词的库:jieba库,这里主要讲解下jieba库的核心知识点。
首先通过如下代码简单显示下jieba库在中文分词方面的使用:
import jieba
word = jieba.cut('我爱北京天安门')
for i in word:
print(i)
打印分词后的结果如下所示:
我
爱
北京
天安门
这里先来将第一条新闻标题进行分词,代码如下:
import jieba
word = jieba.cut(df.iloc[0]['标题'])
result = ' '.join(word)
print(result)
结果如下所示:
信托公司 2019 年 上半年 经营 业绩 概览
通过for循环遍历整张表格,将所有的新闻的标题都进行分词,完整代码如下:
import jieba
words = []
for i, row in df.iterrows():
word = jieba.cut(row['标题'])
result = ' '.join(word)
words.append(result)
words = []
for i, row in df.iterrows():
words.append(' '.join(jieba.cut(row['标题'])))
因为words涵盖了所有新闻标题的分词结果,内容较多,这里通过print(words[0:3])来查看前3条评论的分词结果,如下图所示,每个分词由空格隔开。
['信托公司 2019 年 上半年 经营 业绩 概览',
'首单 信托 型 企业 ABS 获批',
'华能 贵 诚信 托孙磊 : 金融 科技 助力 打造 开放 信托 生态']
pandas库中iterrows()函数,它用来遍历DataFrame的每一行,演示代码如下
for i, row in df.iterrows():
print(i)
print(row)
3、文本向量化基础:建立词频矩阵
下面就需要把这些文字类型的数据转换成数值类型的数据,从而方便构造特征变量,方便模型的训练。在Python中,有一个文本向量化函数CountVectorizer()函数,它可以将文本方便地转换成数值,演示代码如下:
from sklearn.feature_extraction.text import CountVectorizer
test = ['金融 科技 厉害', '华能 信托 厉害']
vect = CountVectorizer()
X = vect.fit_transform(test)
X = X.toarray()
这5个不同的词便构成了这两句话的词袋,CountVectorizer()函数会自动将词袋中的词语进行编号,这里可以通过以下代码来进行验证:
words_bag = vect.vocabulary_
print(words_bag)
4、文本向量化实战:构造特征变量
通过CountVectorizer()文本向量化函数将之前所有分词后的新闻标题进行文本向量化了,代码如下:
from sklearn.feature_extraction.text import CountVectorizer
vect = CountVectorizer()
X = vect.fit_transform(words)
X = X.toarray()
我们可以用vect.vocabulary_代码查看其文本向量化后的词袋:
words_bag = vect.vocabulary_
print(words_bag)
如果只想看到词,而不想看到编号,可以通过get_feature_names()函数实现,代码如下:
words_bag2 = vect.get_feature_names()
print(words_bag2)
获得结果如下,此时便只展示词而不展示词对应的编号了,并且词已经按编号顺序排好了。
我们将文本向量化的代码整合并通过pandas库来更加好的查看整个词频矩阵,代码如下:
from sklearn.feature_extraction.text import CountVectorizer
import pandas as pd
vect = CountVectorizer()
X = vect.fit_transform(words)
X = X.toarray()
words_bag2 = vect.get_feature_names()
df = pd.DataFrame(X, columns=words_bag2)
df.head()
(3)模型搭建与使用
1、通过KMeans算法进行聚类分群
我们提到过我们是根据10个关键词爬取的新闻,那么现在就来利用KMeans算法来搭建模型进行分群聚类,看看它是否能准确地将来自10个不同板块的数据分门别类:
from sklearn.cluster import KMeans
kms = KMeans(n_clusters=10, random_state=123)
k_data = kms.fit_predict(df)
通过代码"print(k_data)"将KMeans算法聚类后的结果展示出来,如下图所示:
其中每一个数字标签就表示一个分类,可以看到通过KMeans算法,所有新闻被分成了10类[0:9],我们打印标签为1的数据来查看该分类中对应的新闻标题内容。
import numpy as np
words_ary = np.array(words)
print(words_ary[k_data == 1])
这里引入Numpy库,将之前13.3.2节存储分词完毕后新闻标题内容的words转换成array数组,然后以逻辑判断的方式提取分类标签为1的数据,结果如下,可以看到分类标签为1的新闻大多都是和Python相关的。
2、通过DBSCAN算法进行聚类分群
DBSCAN 代码如下:
from sklearn.cluster import DBSCAN
dbs = DBSCAN(eps=1, min_samples=3)
d_data = dbs.fit_predict(df)
其中设置模型的参数eps(画圆半径)为1,参数min_samples(圆内最小样本数)为3
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)