低轮廓系数

数据挖掘 Python scikit-学习 k-均值
2022-03-09 04:41:09

我正在对文章销售价值的数据集进行 kmeans 聚类。

每篇文章有 52 个销售价值(每周一个)。我正在尝试自动计算任何未知数据集的最佳集群数量。

我尝试了两个标准:肘法和轮廓系数。

对于轮廓系数,我从 0.059 到 0.117 得到 1 到 20 个集群值,这(在我看来)非常低(听说正常值约为 0.7)。

对于肘部方法,我使用了 kmeans 的惯性_(距离平方和),并将其附加到每次迭代的列表中(也是从 1 到 20)。对于 k=1,我得到的值介于 21782 和对于 k=20 的 15323 之间。

现在我不确定如何解释这些值。我的数据不是那么可分离吗?

编辑:感谢您的回答,因为这似乎是数据/预处理的问题,这是我处理数据的方式:

data = pd.read_csv('/home/dev/Desktop/TD_DM.csv', parse_dates=True, index_col=['DATE'], low_memory=False)
data[['QUANTITY']] = data[['QUANTITY']].apply(pd.to_numeric, errors='coerce')
data_extracted = data.groupby(['DATE','ARTICLENO'])['QUANTITY'].sum().unstack()
print(data_extracted.index)
data_extracted = data_extracted.fillna(value=np.nan)
#data_extracted.index = pd.to_datetime(data_extracted.index.str[:-2], errors="coerce")
data_resampled = data_extracted.resample('W-MON', label='left', loffset=pd.DateOffset(days=1)).sum()
print(data_resampled)

这是打印的 data_resampled 的样子:

2017-12-19           13.0         2600.0            0.0            0.0   
2017-12-26           28.0         2840.0            0.0            0.0   
2018-01-02           34.0         4840.0            0.0            0.0   
2018-01-09           35.0         6140.0            0.0            0.0   
2018-01-16            6.0         5800.0            0.0            0.0   
2018-01-23            3.0         5980.0            0.0            0.0   
2018-01-30            0.0         6100.0            0.0            0.0   
2018-02-06           24.0         5020.0            0.0            0.0   
2018-02-13           60.0         6380.0            0.0            0.0   
2018-02-20           47.0         6220.0            0.0            0.0   
2018-02-27           73.0         5460.0            0.0            0.0   
2018-03-06           69.0         5780.0            0.0            0.0   
2018-03-13           33.0         5520.0            0.0            0.0   
2018-03-20           36.0         5540.0            0.0            0.0   
2018-03-27           27.0         5360.0            0.0            0.0   
2018-04-03           28.0         4920.0            0.0            0.0   
2018-04-10           31.0         5520.0            0.0            0.0   
2018-04-17           46.0         5660.0            1.0           21.0   
2018-04-24           26.0         5040.0           18.0           40.0   
2018-05-01           52.0         5540.0           18.0           40.0   
2018-05-08           36.0         5440.0            3.0           26.0   
2018-05-15           36.0         5720.0            5.0           18.0   
2018-05-22           52.0         4360.0            0.0           22.0   
2018-05-29           52.0         4760.0            0.0           18.0   

列标题将是相应的文章编号。

下一步是定位一整年:

data_extracted = data_resampled.loc['2016-01-01' : '2016-12-31']

然后我开始预处理以删除具有太多 NaN 或 0 的列:

max_nan_count = 5
#there are headers at the 'bottom' too, so remove them
data_extrcated = data_extracted.iloc[:, :-1]
data_extracted = data_extracted.drop(data_extracted.columns[data_extracted.apply(lambda col: col.isnull().sum() > max_nan_count)], axis=1)
data_pct_change = data_extracted.astype(float).pct_change(axis=0).replace([np.inf, -np.inf], np.nan).fillna(0)
data_pct_change.drop([col for col, val in data_pct_change.sum().iteritems() if val == 0 ], axis=1, inplace=True)
print(data_pct_change)

这就是百分比变化的样子:

2016-01-03       0.000000       0.000000       0.000000       0.000000   
2016-01-10       0.284091       0.062500       0.181548       0.252427   
2016-01-17       0.011799       0.117647       0.110831       0.211886   
2016-01-24       0.008746       0.807018       0.092971       0.140725   
2016-01-31      -0.020231      -0.411003       0.056017      -0.186916   
2016-02-07      -0.014749      -0.087912       0.033399      -0.098851   
2016-02-14       0.218563       0.138554       0.136882       0.229592   
2016-02-21      -0.233415      -0.343915      -0.322742      -0.296680   
2016-02-28       0.448718       0.661290       0.535802       0.439528   
2016-03-07      -0.057522      -0.048544      -0.107717       0.012295   
2016-03-14       0.009390      -0.030612       0.234234      -0.062753   
2016-03-21      -0.039535       0.000000      -0.068613       0.032397   
2016-03-28       0.232446       0.210526       0.153605       0.165272   
2016-04-04       0.001965       0.008696      -0.077446       0.028725   
2016-04-11      -0.133333      -0.185345      -0.148748      -0.219895   
2016-04-18       0.108597       0.174603       0.216263       0.199105   
2016-04-25       0.091837      -0.207207      -0.085349       0.016791   
2016-05-02      -0.052336       0.454545       0.149300      -0.023853   
2016-05-09       0.218935       0.000000       0.036536       0.058271   
2016-05-16       0.190939       0.210938      -0.080940       0.156306 

现在我有一个额外的标准化步骤:

normalized_modeling_data = preprocessing.normalize(data_pct_change, norm='l2', axis=0)
normalized_data_headers = pd.DataFrame(normalized_modeling_data, columns=data_pct_change.columns)
normalized_modeling_data = normalized_modeling_data.transpose() 

而这个 normalized_modeling_data 用于 kmeans 聚类。k-means 聚类的结果看起来非常合乎逻辑和可靠,那么我的代码有什么错误吗?

2个回答

剪影值绝对是非常糟糕的。最有可能的是,数据不适合您选择的聚类方法 - 或者 Silhouette 不合适。(但您可能使用了 k-means,这对 Silbouette 来说很好)。改进您对数据的预处理!

惯性值不能跨数据集进行比较,因为它们高度依赖数据。如果将数据缩放 10,惯性值将大 100 倍。由于我们没有您的数据,我们绝对没有机会解释这些值:它们可能很大,也可能很小。

使用肘部方法,如果您引入称为“肘部力量”的量,您还可以尝试以自动方式定量确定集群的数量(而不是使用这种方法通过肉眼来确定)。基本上,它基于肘部图的导数和一些更多的信息增强技巧。有关肘部力量的更多详细信息,请参阅以下出版物的补充信息:

https://iopscience.iop.org/article/10.1088/2632-2153/abd87c