赞
踩
目录
KMeans算法的K代表类别数量,Means代表每个类别内样本的均值,所以KMeans算法又称为K-均值算法。KMeans算法以距离作为样本间相似度的度量标准,将距离相近的样本分配至同一个类别。样本间距离的计算方式可以是欧氏距离,曼哈顿距离,余弦相似度等,KMeans算法通常采用欧氏距离来度量各样本间的距离。
KMeans算法的核心思想是:对每个样本点计算离各个中心点的距离,并将该样本点分配给最近中心点代表的类别,一次迭代完成后,根据聚类结果更新每个类别的中心点,然后重复之前操作再次迭代,直到前后两次分类结果没有差别。下面我们以一个简单案例对KMeans算法的原理进行解释,该案例目的是将样本点聚成3个类别(K=3)
使用一些简单的二维数据来说明如何在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()
散点图如下所示:
银行通常拥有海量的客户,对于不同的客户,银行需要进行不同的营销与工作开展策略,例如对于高收入且风险承受能力强的客户,可以进行重点挖掘业务机会,例如可以给他推销一些收益率高但周期相对较长的理财产品;而对于低收入且风险承受能力较弱的客户,则需要制定不同的营销与工作策略。因此对于银行来说,通常需要将客户进行分群处理,对于不同分群的客户进行不同的处理。
读取数据和创建散点图代码如下:
- 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()
散点图如下所示:
- 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()
DBSCAN (Density-Based Spatial Clustering of Applications with Noise)是一种以密度为基础的空间聚类算法,可以用密度的概念剔除不属于任意类别的噪声点。该算法将簇定义为密度相连的点的最大集合,将具有足够密度的区域划分为簇,并可以发现任意形状的簇。
下面我们以一个简单案例对DBSCAN算法的原理进行解释,我们设定画圆半径为1,圆内最小样本点数为3:
演示完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()
创建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算法聚类效果较差,只能机械地将数据分为左右两部分,而无法以外圆内圆的方式进行区分。
新闻种类繁复多样,可以分为军事,政治,娱乐,财经,体育,科技,历史等等题材,我们需要将每条新闻划分成合适的类别,匹配到正确的版面,以便读者阅读,因此新闻的聚类分群显得十分重要。
- import pandas as pd
- df = pd.read_excel('新闻.xlsx')
- df.head()
df.head()用来展示前五行数据。运行结果如下图所示:
本节中的新闻标题文本,而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)
下面就需要把这些文字类型的数据转换成数值类型的数据,从而方便构造特征变量,方便模型的训练。在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)
通过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()
我们提到过我们是根据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相关的。
DBSCAN 代码如下:
- from sklearn.cluster import DBSCAN
- dbs = DBSCAN(eps=1, min_samples=3)
- d_data = dbs.fit_predict(df)
其中设置模型的参数eps(画圆半径)为1,参数min_samples(圆内最小样本数)为3
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。