1 K-Means Clustering
1.1 Input Data
导入标准模块和数据集
# Import the standard modules to be used in this lab
import pandas as pd
import numpy as np
%matplotlib inline
现在,我们将数据集加载到IPython中,并将其加载到数据帧中。
cust_pd = pd.read_csv("customers.csv")
Now, let’s have a look at the first five data
cust_pd.head()
输出如下:
1.2 Clustering using K-Means
让我们把这些数据画出来,看看我们是否能看到任何群集。为此,我们将使用散点图
Seaborn图书馆。Seaborn是一个基于matplotlib的Python数据可视化库。
首先,我们导入matplotlib和seaborn库。然后我们创建一个数字,并确定他的数字
画出散点图。你能看到多少个集群?
# set the backend of matplotlib to 'inline' to display the plot within Jupyter␣
,→notebook
from matplotlib import pyplot as plt
import seaborn as sns
plt.figure(figsize=(8,5))
sns.scatterplot(x=cust_pd["Income"], y=cust_pd["Debt"])
输出如下:
正如我们所看到的,属性收入和债务是在非常不同的范围,收入是关于10-20倍的债务。因此,在进行聚类之前,我们先对数据进行归一化处理(0 - 1)。在这里,我们通过使用min()和max()函数手动进行规范化。我们还可以用标准化数据的MinMaxScaler。
cust_pd["Income"] = (cust_pd["Income"] - cust_pd["Income"].min()) /␣
,→(cust_pd["Income"].max() - cust_pd["Income"].min())
cust_pd["Debt"] = (cust_pd["Debt"] - cust_pd["Debt"].min()) / (cust_pd["Debt"].
,→max() - cust_pd["Debt"].min())
cust_pd.head()
#from sklearn.preprocessing import MinMaxScaler
#scaler = MinMaxScaler()
#cust_pd = scaler.fit_transform(cust_pd)
#cust_pd = pd.DataFrame(cust_pd, columns=["Income", "Debt"])
#cust_pd.head()
输出如下:
现在让我们从Scikit-Learn导入K-means来创建一个K-means对象。我们将设置数字集群,K = 4。假设有4组。
from sklearn.cluster import KMeans
首先,我们初始化重心。然后,我们创建一个KMeans对象并设置以下参数。N_clusters用于指定集群的数量。Init用于指定初始质心。n_init设置为1,表示K-means算法将运行一次。
init_centroids = np.array([[0.01,0.02],[0.01,0.015],[0.01,0.022],[0.01,0.023]])
kmeans = KMeans(n_clusters=4, init=init_centroids, n_init=1)
kmeans.fit(cust_pd)
输出如下:
我们可以看到算法为最终的簇生成的质心值
centroids = kmeans.cluster_centers_
print(centroids)
输出如下,可以看到这是第二次计算出新的质心。
让我们使用散点图来显示集群。
offset = 0.07
fig, ax = plt.subplots()
sns.scatterplot(x=cust_pd["Income"], y=cust_pd["Debt"])
sns.scatterplot(x=centroids[:,0], y=centroids[:,1])
ax.annotate('Cluster 1', xy=(centroids[0,0]-offset,centroids[0,1]-offset))
ax.annotate('Cluster 2', xy=(centroids[1,0]-offset,centroids[1,1]-offset))
ax.annotate('Cluster 3', xy=(centroids[2,0]-offset,centroids[2,1]-offset))
ax.annotate('Cluster 4', xy=(centroids[3,0]-offset,centroids[3,1]-offset))
输出如下:
质心用黄色的“o”标记。我们添加了一些注释来表示聚类数。现在,让我们使用K-mean模型对数据点进行预测。
offset = 0.07
pred = kmeans.predict(cust_pd)
#cust_pd.insert(2, "Class", pred)
fig, ax = plt.subplots()
sns.scatterplot(x=cust_pd["Income"], y=cust_pd["Debt"], hue=pred)
sns.scatterplot(x=centroids[:,0], y=centroids[:,1])
ax.annotate('Cluster 1', xy=(centroids[0,0]-offset,centroids[0,1]-offset))
ax.annotate('Cluster 2', xy=(centroids[1,0]-offset,centroids[1,1]-offset))
ax.annotate('Cluster 3', xy=(centroids[2,0]-offset,centroids[2,1]-offset))
ax.annotate('Cluster 4', xy=(centroids[3,0]-offset,centroids[3,1]-offset))
输出如下:
K mean ++
接下来我们使用K mean ++来聚类
kmeans = KMeans(n_clusters=4, init='k-means++')
kmeans.fit(cust_pd)
centroids = kmeans.cluster_centers_
print(centroids)
输出四个质心:
: offset = 0.07
pred = kmeans.predict(cust_pd)
fig, ax = plt.subplots()
sns.scatterplot(x=cust_pd["Income"], y=cust_pd["Debt"], hue=pred)
sns.scatterplot(x=centroids[:,0], y=centroids[:,1])
ax.annotate('Cluster 1', xy=(centroids[0,0]-offset,centroids[0,1]-offset))
ax.annotate('Cluster 2', xy=(centroids[1,0]-offset,centroids[1,1]-offset))
ax.annotate('Cluster 3', xy=(centroids[2,0]-offset,centroids[2,1]-offset))
ax.annotate('Cluster 4', xy=(centroids[3,0]-offset,centroids[3,1]-offset))
聚类结果如下:
让我们设置K=6:
: kmeans = KMeans(n_clusters=6)
kmeans.fit(cust_pd)
centroids = kmeans.cluster_centers_
print(centroids)
offset = 0.07
pred = kmeans.predict(cust_pd)
fig, ax = plt.subplots()
sns.scatterplot(x=cust_pd["Income"], y=cust_pd["Debt"], hue=pred)
sns.scatterplot(x=centroids[:,0], y=centroids[:,1])
ax.annotate('Cluster 1', xy=(centroids[0,0]-offset,centroids[0,1]-offset))
ax.annotate('Cluster 2', xy=(centroids[1,0]-offset,centroids[1,1]-offset))
ax.annotate('Cluster 3', xy=(centroids[2,0]-offset,centroids[2,1]-offset))
ax.annotate('Cluster 4', xy=(centroids[3,0]-offset,centroids[3,1]-offset))
ax.annotate('Cluster 5', xy=(centroids[4,0]-offset,centroids[4,1]-offset))
ax.annotate('Cluster 6', xy=(centroids[5,0]-offset,centroids[5,1]-offset))
让我们研究不同数量的簇的距离(惯性)平方之和确定最佳值。
inrt = []
m = 15
for c in range(2,m):
km = KMeans(n_clusters=c)
km.fit(cust_pd.iloc[:,0:2])
inrt.append(km.inertia_)
plt.figure(figsize=(8,5))
plt.plot([c for c in range(2,m)], inrt, marker='.', markersize=14)
plt.xlabel("# of clusters")
plt.ylabel("Inertia (Sum of squared distance)")
输出如下:
我们可以看到,经过6个簇后,惯性并没有明显减少。我们可以得出6是最优集群数。