聚类算法简介
在未知模式识别问题中,通常需要从一堆没有标签的数据中找到其中的关联性。一是要发现数据之间的相似性,也被称为聚类(Clustering);二是要统计数据在空间上的分布,也就是密度估计。聚类可谓无监督学习中最重要的一个作用。
聚类的定义
聚类是将集中具有相似特性的数据分类组织的过程,聚类技术是一种无监督学习。聚类又称为群分析,是研究样本或指标分类问题的一种统计分析方法。聚类与分类的区别是其要划分的类是未知的,常用的聚类分析法中有系统聚类法、有序样本聚类法、动态聚类法、模糊聚类法、图论聚类法和聚类预报法等。
K-means算法概述
K-means聚类算法是基于距离的非层次聚类算法,在最小化误差函数的基础上将数据划分为预定的类别数K,采用距离作为相似性的评价指标,即认为两个对象的距离越近,其相似度越大。
1.首先确定常数K,常数K为最终的聚类类别数。
2.从n个样本中随机选定K个对象作为初始的质心(聚类中心)。
3.计算每个样本与质心的相似度,即通过欧式距离等公式计算每个样本到各个质心的距离,将样本点归到最相似也即最近的类中。
4.重新计算每个类的质心。
5.与前一次计算得到的K个质心比较,如果质心发生变化转至步骤3,否则转至步骤6。
6.当质心不再发生变化时,停止并输出聚类结果。
K-Means聚类算法的结果可能依赖于初始聚类中心的随机选择,使得结果严重偏离全局最优分类。实践中,为了得到较好的结果,通常选择不同的初始聚类中心,多次运行K-Means算法。由于每次都要计算所有样本与每个质心之间的相似度,因此在大规模的数据集上,K-Means算法收敛速比较慢。
K-Means算法实现
数据集为客户销毁行为特征数据,其中R代表平均消费间隔天数,F代表消费的次数,M代表消费的金额。数据集可从以下百度网盘中获得:
链接: https://pan.baidu.com/s/1-G7gb-ZipnCM7IyKAZtcXA
提取码: 4qfk 。
在数据预处理环节,使用z-score 标准化方法。即零 - 均值标准化(常用方法)
y=(x-μ)/σ 是一种统计的处理,基于正态分布的假设,将数据变换为均值为 0、标准差为 1 的标准正态分布。但即使数据不服从正态分布,也可以用此法。特别适用于数据的最大值和最小值未知,或存在孤立点。
使用sklearn进行实现:
# -*- coding: utf-8 -*-
import matplotlib.pyplot as plt
import pandas as pd
# 参数初始化
inputfile = 'data/consumption_data.xls' # 销量及其他属性数据
outputfile = 'data/data_type.xls' # 保存结果的文件名
k = 3
iteration = 500
data = pd.read_excel(inputfile, index_col = 'Id') # 读取数据
data_zs = 1.0*(data - data.mean())/data.std() # 数据标准化
from sklearn.cluster import KMeans
model = KMeans(n_clusters = k, n_jobs = 4, max_iter = iteration,random_state=1234)
# 分为k类,并发数4,迭代次数为500
model.fit(data_zs) # 开始聚类
#print(model.labels_) 代表分类编号。
# 简单打印结果
r1 = pd.Series(model.labels_).value_counts() # 统计各个类别的数目
#print(r1)
r2 = pd.DataFrame(model.cluster_centers_) # 找出聚类中心
#print(r2)
#print([r2, r1])
r = pd.concat([r2, r1], axis = 1) # 横向连接(0是纵向),得到聚类中心对应的类别下的数目
print(r)
r.columns = list(data.columns) + ['类别数目'] # 重命名表头
# 详细输出原始数据及其类别
r = pd.concat([data, pd.Series(model.labels_, index = data.index)], axis = 1) # 详细输出每个样本对应的类别
r.columns = list(data.columns) + ['聚类类别'] # 重命名表头
print(r.columns)
r.to_excel(outputfile) # 保存结果
def density_plot(data): # 自定义作图函数
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
p = data.plot(kind='kde', linewidth = 2, subplots = True, sharex = False)
[p[i].set_ylabel(u'密度') for i in range(k)]
plt.legend()
return plt
for i in range(k):
density_plot(data[r[u'聚类类别']==i])
plt.show()
from sklearn.manifold import TSNE
tsne = TSNE(random_state=105)
tsne.fit_transform(data_zs)#进行数据降维
tsne = pd.DataFrame(tsne.embedding_,index=data_zs.index)#转换数据格式
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False #用来正常显示负号
#不同类别用不同颜色和样式绘图
d = tsne[r['聚类类别']==0]
plt.plot(d[0],d[1],'r.')
d = tsne[r['聚类类别']==1]
plt.plot(d[0],d[1],'go')
d = tsne[r['聚类类别']==2]
plt.plot(d[0],d[1],'b*')
plt.show()