我试图在一个数据集上使用K-means聚类,该数据集可以在此链接找到,仅使用关于客户的变量。问题是8个变量中有7个是分类变量,因此我对它们使用了一键编码(one hot encoder)。
为了使用肘部法(elbow method)选择理想的聚类数量,我运行了从2到22个聚类的KMeans,并绘制了inertia_值的图表。但形状并不像肘部,更像是一条直线。
我做错了什么吗?
import pandas as pdimport numpy as npimport matplotlib.pyplot as pltfrom sklearn.cluster import KMeans from sklearn import preprocessingfrom sklearn.preprocessing import StandardScalerbank = pd.read_csv('bank-additional-full.csv', sep=';') #available at https://archive.ics.uci.edu/ml/datasets/Bank+Marketing# # 1. 仅选择关于客户的信息cli_vars = ['age', 'job', 'marital', 'education', 'default', 'housing', 'loan']bank_cli = bank[cli_vars].copy()#2. 对分类变量应用一键编码X = bank_cli[['job', 'marital', 'education', 'default', 'housing', 'loan']]le = preprocessing.LabelEncoder()X_2 = X.apply(le.fit_transform)X_2.valuesenc = preprocessing.OneHotEncoder()enc.fit(X_2)one_hot_labels = enc.transform(X_2).toarray()one_hot_labels.shape #(41188, 33)#3. 连接数值和分类变量X = np.concatenate((bank_cli.values[:,0].reshape((41188,1)),one_hot_labels), axis = 1)X.shapeX = X.astype(float)X_fit = StandardScaler().fit_transform(X)X_fit#4. 计算2到22个聚类的K-means函数def calcular_cotovelo(data): wcss = [] for i in range(2, 23): kmeans = KMeans(init = 'k-means++', n_init= 12, n_clusters = i) kmeans.fit(data) wcss.append(kmeans.inertia_) return wcsscotovelo = calcular_cotovelo(X_fit)#5. 绘制图表以查看肘部曲线并选择理想的聚类数量plt.plot(cotovelo)plt.show()
这是选择聚类的惯性图表。它不是肘形曲线,数值也很高。
回答:
K-means不适合处理分类数据。你应该考虑使用k-prototypes,它结合了k-modes和k-means,能够对混合的数值和分类数据进行聚类。
在Python中可以找到k-prototypes的实现。
然而,如果你只考虑数值变量,你可以看到使用K-means标准的肘部曲线:
为了理解为什么在使用K-means处理数值和分类数据时看不到任何肘部曲线,你可以查看每个聚类中的点数。你会发现,每次增加聚类数量时,都会形成一个新聚类,包含的点数很少,这些点在前一步骤中属于一个大聚类,因此标准值仅比前一步骤略低。