在 python 中绘制大数据集集群

Plot big dataset clusters in python

所以基本上我对 python 的 sklearn 和 ML 有点陌生。我习惯了 RapidMiner 和其他 GUI 工具。我有超过 200 万行和 5 列的数据集,它们是我的主成分(大约 98% 的方差)。我用 kmeans 执行了聚类并获得了标签。我已经知道集群的数量必须是 4,并使用 kmeans++ 生成的质心初始化算法。

from sklearn.cluster import KMeans
preds = KMeans(n_clusters=4, init=centers_init).fit_predict(sc_norm_pca_data)
result = np.append(sc_norm_pca_data, preds.reshape([2208556, 1]), axis=1) # append labels to data

现在我面临两个问题:

  1. 我不知道自从 组件数量为 5。也许我可以使用 前 3 个 PC 或取标签并将它们附加到 pre-PCA 数据集。

  2. 我尝试使用 前 2 台电脑,但显然使用 matplotlib 绘制超过 200 万 点是个坏主意。所以,我再次尝试了 10k 行的样本 但 5 分钟后仍然没有。

    idx = np.random.randint(10, size=10000)
    result = result[idx,:]
    plt.scatter(result[:, 0], result[:, 1], c=result[:,result.shape[1]-1]) # 5th column has the labels
    

我希望收到一些关于我做错了什么以及如何以正确的方式处理这些类型的情况的建议。还有,剧情这么长很正常吧? 我正在使用 Colab 并在 PCA 之前做了一些预处理(清理、标准化等)。

k-means 聚类的结果可以使用观测数据的主要方向进行可视化。这些主要方向是使用 PCA 算法计算的。这是一个使用 iris 数据集执行此操作的简单示例:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.decomposition import PCA
from sklearn.datasets import load_iris
from sklearn import preprocessing
from sklearn.cluster import KMeans
from sklearn.decomposition import PCA
import itertools

iris = load_iris()

# get flower data
X = iris['data']

# get flower families
labels = iris['target']
nclusters = np.unique(labels).size

# scale flower data
scaler = preprocessing.StandardScaler()
scaler.fit(X)
X_scaled = scaler.transform(X)

# instantiate k-means
seed = 0
km = KMeans(n_clusters=nclusters, random_state=seed)
km.fit(X_scaled)

# predict the cluster for each data point
y_cluster_kmeans = km.predict(X_scaled)

# Compute PCA of data set
pca = PCA(n_components=X.shape[1], random_state=seed)
pca.fit(X_scaled)
X_pca_array = pca.transform(X_scaled)
X_pca = pd.DataFrame(X_pca_array, columns=['PC%i' % (ii + 1) for ii in range(X_pca_array.shape[1])]) # PC=principal component

# decide which prediction labels to associate with observed labels
# - search each possible way of transforming observed labels
# - identify approach with maximum agreement
MAX = 0
for ii in itertools.permutations([kk for kk in range(np.unique(y_cluster_kmeans).size)]):

    change = {jj: ii[jj] for jj in range(len(ii))}

    changedPredictions = np.ones(y_cluster_kmeans.size) * -99
    for jj in range(len(ii)):
      changedPredictions[y_cluster_kmeans == jj] = change[jj]

    successful = np.sum(labels == changedPredictions)
    if successful > MAX:
        MAX = successful
        bestChange = change

# transform predictions to match observations
changedPredictions = np.ones(y_cluster_kmeans.size) * -99
for jj in range(len(ii)):
  changedPredictions[y_cluster_kmeans == jj] = bestChange[jj]

# plot clusters for observations and predictions
fig, ax = plt.subplots(1, 2, figsize=(7, 3))
ax[0].scatter(X_pca['PC1'], X_pca['PC2'], c=changedPredictions)
ax[1].scatter(X_pca['PC1'], X_pca['PC2'], c=labels)
ax[0].set_title('Prediction')
ax[1].set_title('Truth')

回答问题(1):

您可以选择 PCA 组件的数量,并且有很多方法可以实现二维以上数据的可视化。如果我必须使用 3 个 PCA 组件绘制数据,我可能会创建前两个组件的散点图动画,及时合并第三个组件。

可以通过检查每个组件捕获的变化(例如,特征值)来确定适当数量的 PCA 组件,这可以使用 pca.explained_variance_:

来完成
eigenvalues = pca.explained_variance_
eigenvalues /= eigenvalues.sum()
plt.plot(eigenvalues, marker='o')
plt.xlabel('PC Dimension')
plt.ylabel('Normalized Eigenvalue')

正如我们所见,前两个 PCA 分量捕获了大约 90% 的方差。

因此,您可以通过显示它们对总方差的相对贡献来证明使用三个 PCA 组件的合理性。通常只使用两个,因为它们通常捕获数据的大部分变化。

回答问题(2):

绘制每个点都需要一些时间,这段时间加起来将有数百万个点。在这个线程中有一些关于大数据集散点图的讨论Scatter plot with a huge amount of data,尽管似乎没有时间来制作具有数百万个点的散点图。

因此,与其绘制整个数据集,不如只绘制数据的一个子集,使用“有趣的”点随机选择点 and/or 似乎最实用。想想你想在这些情节中捕捉到什么信息,并围绕这些信息塑造你的情节。也许简单地绘制前一千行数据就足够了,或者选择要绘制的点可能需要复杂的机器学习算法。最佳绘图方法实际上取决于绘图的意图。

您可能对检测异常值感兴趣。检测异常值的经典方法是使用距每个聚类中心的距离并选择距每个质心距离较大的点。在这个例子中,20% 的数据用实心标记绘制,表示它们是离群值,40% 的数据用半透明标记绘制,表示它们是随机选择的。识别异常值时保留的数据量由 percentile 变量控制。

from scipy.spatial.distance import cdist

# convert centroids to PCA space
centroids = km.cluster_centers_
pce_centroids = pca.transform(centroids)

# compute distances from centroids using first 2 components
alldistances = cdist(pce_centroids[:, :2], X_pca_array[:, :2])
distances = alldistances.min(0)

# plot large distances
percentile = 80
outliersIDX = np.where(distances > np.percentile(distances, percentile))
colors = np.array(['purple', 'green', 'gold'])
plt.scatter(X_pca_array[outliersIDX, 0], X_pca_array[outliersIDX, 1], c=colors[changedPredictions[outliersIDX].astype(int)])

# A random subset of the full data set can be plotted with the outliers
np.random.seed(123)
randIDX = np.random.choice(range(X.shape[0]), 100)
plt.scatter(X_pca['PC1'][randIDX], X_pca['PC2'][randIDX], c=changedPredictions[randIDX], alpha=0.2)

如果在查看绘图时难以获取所有数据,最好找到一种 numerical/statistical 方法来评估 k-means 聚类。举个简单的例子,在我的 Iris 数据集中,我可以统计预测失败的次数:

print(r'%.1f percent successful predictions' % (100 * np.sum(labels == changedPredictions) / labels.size))

   83.3 percent successful predictions