kmeans python变量重要性_k-means聚类算法优缺点?

K-Means是我们最常用的基于欧氏距离的聚类算法,它的基本思想是,两个目标的距离越近,相似度越大。

K-Means算法的目标函数

K-Means算法要实现的目标函数是:

其中,C1,C2,...,Ck是分别是k个cluster的中心点;C(Xi)表示Xi这个点所属于的cluster的中心点;d²( , )表示求两个点的距离的平方。

用通俗的话说,K-Means算法要实现的目的是:使得样本空间所有的非中心点,到它们各自所属的cluster的中心点的距离的平方,的和最小。

上述问题是一个NP-Hard问题。因此,一般是采用坐标下降(Coordinate Decendet)的方法求解。坐标下降法属于非梯度优化的方法,它在每一步迭代中沿着一个坐标轴的方向进行探索,通过循环使用不同的坐标来达到求解目标函数的局部最小值。坐标下降算法。来源:https://zh.wikipedia.org/zh-cn/%E5%9D%90%E6%A0%87%E4%B8%8B%E9%99%8D%E6%B3%95

如上图所示,假设总共有两个维度x,y:我们首先选择一个初始位置(x,y),然后假设x未知并将y的值代入目标函数中,令目标函数的导数为0,可以求得此时最佳的x的值。

然后又假设y未知并将刚刚求得的x的值代入目标函数,令目标函数的导数为0,可以求得此时最佳的y。

重复执行第1步和第2步,目标函数会逐渐接近极小值点,直到达到了极小值点后停止。

收敛的过程如上图中的红色箭头所示。在有更多维度的时候,也是同样的道理,一次只对于一个维度进行最优化。

坐标下降法一般要求目标函数是可微的凸函数,此时我们求得的极小值才能是全局最小值。

在使用K-Means之前,可以先用PCA,使得各个变量之间尽可能独立。否则如果两个变量之间有较强的关联性的时候,函数收敛的速度会非常慢。

K-Means算法的过程从样本中所有的n个点中,随机选取其中的k个做中心点(见第1行的第1、2张图;k的大小是事先指定的);

将样本中剩余n-k个样本点分别划分到离它们最近的中心点上,这里的划分完成后,就做完了一次聚类(见第1行的第3张图);

计算每一个类的平均值,并将每一个平均值作为新的中心点(见第2行的第1张图);

重复执行步骤2和3,直到中心点的位置不再发生变化(收敛;见最后四张图)。K-Means算法的实现过程

K-Means的Python实现

1.数据预处理,去离群点。因为k-means很容易受到离群点的影响。我的dataset比较干净,因此没有处理,直接载入数据。

import pandas as pd

import os

from sklearn.preprocessing import MinMaxScaler

from sklearn.model_selection import train_test_split

import numpy as np

from sklearn.cluster import KMeans

from scipy.spatial.distance import cdist

import matplotlib.pyplot as plt

from sklearn.cluster import MiniBatchKMeans

# load the d

os.chdir(r'D:\')

data = pd.read_csv('transactions_n100000.csv')

2.对于离散的变量进行编码,例如进行one-hot encoding。

def enco(variable,data):

data[variable]

dummies = pd.get_dummies(data[variable], prefix=variable,dtype='float')

dummies

data = data.join(dummies)

return data

# one-hot encoding

data=enco('location',data)

data=enco('item_name',data)

3.对于数据划分训练集和测试集。注意,必须要先划分数据,再进行归一化。如果你把整个数据集一起归一化再划分的话,会把训练集的信息加入到测试集中,造成data leakage。

# train-test split

train, test = train_test_split(data,test_size=0.3)

4.对于数据进行归一化,防止scale比较大的变量在里面欺凌弱小、一家独大。具体过程为:对于训练集用k-means算法进行fit,得到包含训练集均值和标准偏差的scaler

用fit出来的结果分别transform训练集和测试集

注意这个流程,测试集也是用训练集的fit结果来transform的

# Min-Max scale

# fit

scaler = MinMaxScaler()

scaler.fit(train)

# transform

train_scaled = pd.DataFrame(scaler.transform(train),columns=data.columns)

test_scaled = pd.DataFrame(scaler.transform(test),columns=data.columns)

5.用elbow method选择最佳的k值。这个地方要注意,由于K-Means的聚类结果是局部最优,因此我们一般可以多聚类几次,求SSE的均值作为纵坐标,避免局部最优解。

# KMeans

# choose k value with elbow method

K = range(1, 20)

meanDispersions = []

for k in K:

kmeans = KMeans(n_clusters=k)

# kmeans = MiniBatchKMeans(n_clusters=k) # 如果数据量大的话,例如十万条以上,可以用mini-batch kmeans

kmeans.fit(train_scaled)

#理解为计算某个与其所属类聚中心的欧式距离

#最终是计算所有点与对应中心的距离的平方和的均值

meanDispersions.append(sum(np.min(cdist(train_scaled, kmeans.cluster_centers_, 'euclidean'), axis=1)) / train_scaled.shape[0])

plt.plot(K, meanDispersions, 'bx-')

plt.xlabel('k')

plt.ylabel('Average Dispersion')

plt.title('Selecting k with the Elbow Method')

plt.show() # k=8

在运行上面的代码块后,我们得到了Elbow的图如下。用elbow method选择最佳的k值

如上图所示,在k>8以后,认为折线的斜率几乎不变了,因此根据elbow method,可以选的k=8。

6. 进行k=8的kmeans聚类。

# cluster

kmeans = KMeans(n_clusters=8).fit(train)

train['type']=kmeans.labels_

train['type'].unique()

K-Means的优点:原理简单,收敛速度快,这个是业界用它最多的重要原因之一。

调参的时候只需要改变k一个参数。

算法的原理简单,可解释性好

K-Means的缺点:对于离群点和噪音点敏感。例如在距离中心很远的地方手动加一个噪音点,那么中心的位置就会被拉跑偏很远。

k值的选择很难确定。

只能发现球状的簇。在k-means中,我们用单个点对cluster进行建模,这实际上假设了各个cluster的数据是呈高维球型分布的,但是在生活中出现这种情况的概率并不算高。例如,每一个cluster是一个一个的长条状的,k-means的则根本识别不出来这种类别(这种情况可以用GMM)。实际上,k-means是在做凸优化,因此处理不了非凸的分布。

如果两个类别距离比较近,k-means的效果也不会太好。

初始值对结果影响较大,可能每次聚类结果都不一样。

结果可能只是局部最优而不是全局最优。

K-Means模型确定k的值的其他方法把样本的二维、三维散点图画出来,观察一下样本的分布,然后再决定k的值。如果维度大于三维,可以使用PCA降维到三维。

使用轮廓系数(Sihouette Coefficient)判断。轮廓系数结合了聚类的凝聚度(Cohesion,下图中的a(i))和分离度(Separation,下图中的b(i)),可以用来评价聚类的效果。该值处于[-1,1]之间。越接近1,表示聚类效果越好。来源:https://blog.csdn.net/wangxiaopeng0329/article/details/53542606来源:http://studio.galaxystatistics.com/report/cluster_analysis/article4/

更多的内容建议看一下 @微调 这篇回答微调:如何正确使用「K均值聚类」?​zhuanlan.zhihu.com

你可能感兴趣的:(kmeans,python变量重要性)