前言
KMeans是最常用的最简单的聚类算法。它的效率是常见的一系列聚类算法中最高的。但受向量大小、数据量和类中心数量影响,聚类速度变慢。这里分享一些简单的技巧或者一些坑。
加速方法分享
1. Spark失效
Spark采用并行分布式计算,速度相当高和快。但是遇到kmeans,spark似乎失效了。在我的实验环境中,观察到:Spark集群部署3个8核心worker,但实际中只有一台worker在工作,这是因为kmean算法底层实现上的一些原因,它只能在一台机器的CPU上进行运算,除非改动其底层。
所以,与其开spark不如在一台多核CPU上进行计算。
由于各种算法底层原理不一样,不排除其他的模型在spark上可以实现真正并行,如此可以提升速度。
2. Sklearnex加速KMeans计算
sklearnex是一个sklearn加速包,大约可以提升几倍到千倍的速度。它是针对Intel
平台的,只对Intel CPU
有效,且CPU性能越好加速效果越显著。AMD CPU
就算了,如果你是Linux系列的系统,使用lscpu
命令即可查看确认CPU信息,windows和mac自行百度。
我的数据集是55万行384位数据,开了Sklearnex速度提升了10倍。这个速度提升相当惊艳,值得一试。
2.1 安装
pip install scikit-learn scikit-learn-intelex -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
2.2 开启加速
>>> from sklearnex import patch_sklearn
>>> patch_sklearn() # 这个函数用于开启加速sklearn,出现如下语句就表示OK!
Intel(R) Extension for Scikit-learn* enabled (https://github.com/intel/scikit-learn-intelex)
3. 降维
Kmeans在计算过程中,肯定需要度量样本间距离或者相似度。以欧式距离和Cosine相似度为例,这两种计算方法的时间复杂度都是O(n),n为维度数,所以降低维度肯定可以加快速度。维度减半,时间大约减半。
from sklearn.decomposition import PCA
pca = PCA(n_components=0.9) # 原来向量中的信息为100%,希望压缩后的向量保留了90%信息。压缩后的列数是按照90%计算的。
decomposed_mtx = pca.fit_transform(raw_mtx)
4. 减少数据
这条很简单,就是减少数据量。看起来也很愚蠢,怎么能随便删除数据呢!但是工业场景中,其实我们很多数据都是重复的,而很多聚类算法对重复或者异常值是敏感的。所以减少无效重复和异常值,如果可以大量降低数据量,不失为一个好的方法。
5. GPU
有很多GPU版本的KMeans算法包,大多数基于cuda或者torch、tensorflow的。
6. 放弃轮廓系数方法
如果你要找最优类别数,在大数据量情况下,不要直接使用轮廓系数方法,因为它的时间复杂度为
O
(
n
2
)
O(n^2)
O(n2),甚至比聚类过程速度都要慢。一半情况下用误差平方和(在sklearn的kmeans算法里,kmean.inertia_
就是误差平方和),或者对抽样样本计算轮廓系数。
以下代码是在jupyter中直接运行的。
import pandas as pd
# 寻找最佳 类别数
NS = list(range(1100, 2001, 100))
for n in NS:
print(n)
begin = time.time()
kmean = KMeans(n_clusters=n)
row_clusters = kmean.fit_predict(pca_mtx)
km_models.append(kmean)
N_info.append([n, kmean.inertia_])
end = time.time()
print(n, end-begin)
n_info_pd = pd.DataFrame(N_info, columns=['n', 'sse'])
# 打印网格
axe1 = n_info_pd.plot(x='n', y='sse', ylabel='sse',
grid=True, # 显示网格线
legend=False # 不现实legend
)