最全面的K-means聚类指南

在本文中,我们将全面介绍K-means聚类及其扩展。我们将研究聚类,它为什么重要,它的应用,然后深入研究K-means聚类(包括如何在真实数据集上用Python实现它)。

最全面的K-means聚类指南

1. 介绍

每当我在网站上遇到推荐引擎时,我都迫不及待地将其分解并理解它的底层是如何工作的。我想这是成为数据科学家的最重要的品质之一!

这些系统真正令我着迷的是我们如何将类似的物品,产品和用户组合在一起。这种分组或分段适用于各个行业。这就是聚类概念在数据科学中如此重要的原因。

聚类有助于我们以独特的方式理解我们的数据 – 通过将事物分组。

在本文中,我们将全面介绍K-means聚类及其扩展。我们将研究聚类,它为什么重要,它的应用,然后深入研究K-means聚类(包括如何在真实数据集上用Python实现它)。

2. 什么是聚类?

让我们用一个简单的例子来解决问题。银行希望向其客户提供信用卡优惠。目前,他们查看每个客户的详细信息,并根据这些信息,决定应该向哪个客户提供哪个优惠。

现在,该银行可能拥有数百万客户。分别查看每个客户的详细信息然后做出决定是否有意义?当然没有!这是一个手动过程,需要花费大量时间。那么银行可以做些什么呢?一种选择是将其客户划分为不同的组。例如,银行可以根据客户的收入对其进行分组:
最全面的K-means聚类指南

银行现在可以制定三种不同的策略或优惠,每组一个。在这里,他们不必为个人客户创建不同的策略,而只需制定3种策略。这将减少时间和人力。我上面显示的组称为簇(clusers),创建这些组的过程称为聚类(clustering)。在形式上,我们可以说:

聚类是基于数据中的模式将整个数据划分为组(也称为簇)的过程。

你能猜出聚类是哪种类型的学习问题吗?这是一个有监督还是无监督的学习问题吗?

考虑一下,并利用我们刚才看到的例子。是的,聚类是一种无监督的学习问题!

2.1. 聚类为什么是一个无监督学习问题?

假设你正在开展一个需要预测市场销售的项目:
最全面的K-means聚类指南

或者,你的任务是预测是否批准贷款的项目:
最全面的K-means聚类指南

在上面提到的两个例子中,我们有一个想要预测的固定的目标。在销售预测问题中,我们必须根据outlet_size,outlet_location_type等预测Item_Outlet_Sales,并且在贷款审批问题中,我们必须根据Gender,Married,ApplicantIncome等预测Loan_Status。

因此,当我们根据一组给定的预测因子变量或自变量去预测一个目标变量时,这些问题被称为监督学习问题。

现在,可能存在没有预测目标变量的情况。

没有任何固定目标变量的这些问题被称为无监督学习问题。在这些问题中,我们只有自变量而没有目标/因变量。

在聚类中,我们没有预测目标变量。我们查看数据然后尝试进行类似的观察并形成不同的簇。因此,这是一个无监督的学习问题。

我们现在知道什么是簇和聚类的概念。接下来,让我们看一下在形成簇时我们必须考虑的这些簇的属性。

2.2. 簇的属性

还是以上面提到银行业务为例子,为简单起见,我们假设银行只想利用客户的收入和债务来进行细分。他们收集了客户数据并使用散点图对其进行可视化:
最全面的K-means聚类指南

X轴代表客户的收入,y轴代表债务的数额。在这里,我们可以清楚地看到这些客户可以分为4个不同的组,如下所示:
最全面的K-means聚类指南

这就是聚类怎样从数据创建组(簇)。银行可以进一步使用这些组制定策略并为其客户提供折扣。那么让我们来看看这些组的属性。

属性1

组中的所有数据点应该彼此相似。让我用上面的例子来说明它:
最全面的K-means聚类指南

如果特定组中的客户彼此不相似,那么他们的要求可能会有所不同,对吧?如果银行给他们相同的报价,他们可能不喜欢它,对银行可能会比较失望,因此效果并不理想。

同一组中拥有类似的数据点有助于银行使用有针对性的营销。你可以考虑日常生活中的类似示例,并思考聚类将如何(或已经)影响业务战略。

属性2

来自不同组的数据点应尽可能不同。如果你掌握了上述属性,这将是直观有意义的。让我们再次使用相同的示例来理解此属性:
最全面的K-means聚类指南

你认为上面哪种是更好的簇结果?如果你看一下案例一:
最全面的K-means聚类指南

红色和蓝色簇中的客户彼此非常相似。红色簇中的前四个点与蓝色簇中的前两个客户具有相似的属性,他们有高收入和高债务。在这里,我们对它们进行了不同的聚类。然而,如果你看看案例二:
最全面的K-means聚类指南

红色簇与蓝色簇中的客户完全不同。红色簇中的所有客户都有高收入和高负债,蓝色簇中的客户收入高,债务价。显然,在这种情况下,我们有更好的客户群。

因此,来自不同簇的数据点应尽可能彼此不同,以形成更有意义的簇。

到目前为止,我们已经了解了聚类是什么以及聚类的不同属性。但为什么我们需要聚类?让我们在下一节中清楚解答这个疑问,看一下簇的一些应用。

2.3. 聚类在真实世界中的应用

聚类是业界广泛使用的技术。它实际上被用于各个领域,从银行到推荐引擎,文档聚类到图像分割。

a. 客户细分

我们之前介绍了这一点,聚类最常见的应用之一是客户细分。但它不仅限于银行业务,该战略涉及各种功能,包括电信,电子商务,体育,广告,销售等。

b. 文档聚类

这是聚类的另一种常见应用。假设你有多个文档,并且需要将类似的文档集中在一起。聚类可帮助我们对这些文档进行分组,使类似文档位于同一簇中。
最全面的K-means聚类指南

c. 图像分割

我们还可以使用聚类来执行图像分割。在这里,我们尝试将图像中的相似像素聚集在一起。我们可以应用聚类来创建在同一组中具有相似像素的各个簇。
最全面的K-means聚类指南

你可以参考这篇文章[1],了解我们如何利用聚类进行图像分割任务。

d. 推荐引擎

聚类也可用于推荐引擎。假设你想向朋友推荐歌曲。你可以查看该人喜欢的歌曲,然后使用聚类查找类似的歌曲,最后推荐最相似的歌曲。
最全面的K-means聚类指南

还有更多的应用,我相信你已经想过了。你可以在下面的评论部分分享这些应用。接下来,让我们看看我们如何评估我们聚类出来的簇。

2.4. 了解聚类的不同评估度量标准

聚类的主要目的不仅仅是创建簇,而是创建好的和有意义的簇。我们在下面的例子中看到了这一点:
最全面的K-means聚类指南

在这里,我们只使用了两个特征,因此我们很容易可视化并决定哪些簇更好。

不幸的是,这不是真实世界场景的工作方式,因为我们将拥有大量的特征。让我们再次看一下客户细分示例,我们将拥有客户收入,职业,性别,年龄等功能。将所有这些功能可视化并决定更好,更有意义的簇对我们来说是不可能的。

这是我们可以利用评估指标的地方。让我们讨论其中的一些,并了解我们如何使用它们来评估簇的质量。

a. Inertia

回想一下上面介绍的簇的第一个属性。这就是Inertia评估。Inertia实际上计算簇内所有点到该簇的质心的距离的总和。

我们为所有簇计算这个总和,最终Inertia值是所有这些距离的总和。簇内的这个距离称为簇内距离(intracluster distance.)。因此,Inertia为我们提供了簇内距离的总和:
最全面的K-means聚类指南

现在,你认为一个好的簇的Inertia值应该是什么?小的Inertia好还是大的Inertia好?我们希望同一簇中的点彼此相似,对吧?因此,它们之间的距离应尽可能小。

记住这一点,我们可以说Inertia越小,我们的聚类越好。

b. Dunn Index

我们现在知道Inertia试图最小化簇内距离。它正试图划分更紧凑的簇。

让我这样说吧 – 如果一个簇的质心与该簇中的点之间的距离很小,则意味着这些点彼此更接近。因此,Inertia可确保满足簇的第一个属性。但它并不关心第二个属性,不同的簇应尽可能彼此不同。

这就是Dunn Index可以用来评估的地方。
最全面的K-means聚类指南

除了质心和点之间的距离,Dunn Index还考虑了两个簇之间的距离。两个不同簇的质心之间的距离称为簇间距离(inter-cluster distance)。让我们看看Dunn Index指数的公式:
最全面的K-means聚类指南

Dunn Index是簇间距离的最小值与簇内距离的最大值之比。

我们希望最大化Dunn Index,Dunn Index的值越大,簇就越好。让我们直观理解下Dunn Index:
最全面的K-means聚类指南

为了最大化Dunn Index的值,分子应该是最大的。在这里,我们采用最小的簇间距离。因此,即使是最近的簇之间的距离也应该更大,这最终将确保簇彼此远离。
最全面的K-means聚类指南

此外,分母应该是最小的,以最大化Dunn Index。在这里,我们采取最大的簇内距离。同样,这里的直觉也是一样的。簇质心和点之间的最大距离总和应该最小,这最终将确保划分的簇紧凑。

3. K-means聚类介绍

回想一下簇的第一个属性,它表明簇中的点应该彼此相似。因此,我们的目标是最小化簇内点之间的距离。

有一种算法试图通过它们的质心最小化簇中点的距离,那就是K-means聚类技术。

K-means是一种基于质心的算法,或基于距离的算法,我们计算将点分配给一个簇的距离。在K-means中,每个聚类都与一个质心相关联。

K-means算法的主要目的是最小化点与它们各自的簇质心之间的距离之和。

现在让我们举个例子来了解K-means实际上是如何工作的:
最全面的K-means聚类指南

我们有这8个点,我们想要应用K-means来为这些点划分簇。下面将演示我们是怎样做到的。

第一步:选择簇的数目k

K-means的第一步是选择簇的数目k。

第二步:从数据中选择k个随机点作为质心

接下来,我们为每个簇随机选择质心。假设我们想要有2个簇,所以k在这里等于2。然后我们随机选择质心:
最全面的K-means聚类指南

这里,红色和绿色圆圈代表这些簇的质心。

第三步:将所有点分配给到某个质心距离最近的簇

一旦我们初始化了质心,我们就将每个点分配给到某个质心距离最近的簇:
最全面的K-means聚类指南

在这里,你可以看到更接近红点的点被分配给红色簇,而更接近绿点的点被分配给绿色簇。

第四步:重新计算新形成的簇的质心

现在,一旦我们将所有点分配到任一簇中,下一步就是计算新形成的簇的质心:
最全面的K-means聚类指南

在这里,红色和绿色叉号是新的质心。

第五步:重复第三步和第四步

然后我们重复第三步和第四步:
最全面的K-means聚类指南

计算质心并基于它们与质心的距离将所有点分配给簇的步骤是单次迭代。但我们什么时候应该停止这个过程?它不能永远运行下去对吧?

停止K-means聚类的标准

基本上有三种停止标准可用于停止K-means算法:

如果新形成的簇的质心没有变化,我们就可以停止算法。即使在多次迭代之后,所有簇都还是相同的质心,我们可以说该算法没有学习任何新模式,并且它是停止训练的标志。

另一个明显的迹象表明,在多次迭代训练的之后,如果数据点仍然都在同一簇中,我们应该停止训练过程。

最后,如果达到最大迭代次数,我们可以停止训练。假设我们将迭代次数设置为100。在停止之前,该过程将重复100次迭代。

从零开始在Python中实现K-means聚类

是时候启动我们的 Jupyter notebooks(或者你使用的任何一款IDE)!

我们将在大型市场销售数据集上进行处理,你可以在此处下载[2]

我建议你在此处[3]阅读有关数据集和问题陈述的更多信息。这将帮助你可视化我们正在处理的工作(以及我们为什么这样做)。这是任何数据科学项目中的两个非常重要的问题。

首先,导入所有必需的库:

import pandas as pd
import numpy as np
import random as rd
import matplotlib.pyplot as plt

现在,我们将读取CSV文件并查看数据的前五行:

data = pd.read_csv('clustering.csv')
data.head()

最全面的K-means聚类指南

3对于本文,我们将仅从数据中获取两个变量:“LoanAmount”和“ApplicantIncome”。这样也可以轻松地将步骤可视化。让我们选择这两个变量并可视化数据点:

X = data[["LoanAmount","ApplicantIncome"]]
#可视化
plt.scatter(X["ApplicantIncome"],X["LoanAmount"],c='black')
plt.xlabel('AnnualIncome')
plt.ylabel('Loan Amount (In Thousands)')
plt.show()

最全面的K-means聚类指南

K-means的步骤1和2是关于选择簇数(k)和为每个簇选择随机质心。我们将选择3个簇,然后从数据中随机选择样本作为质心:

#簇的个数
K=3
# 随机选择观察值作为簇心
Centroids = (X.sample(n=K))
plt.scatter(X["ApplicantIncome"],X["LoanAmount"],c='black')
plt.scatter(Centroids["ApplicantIncome"],Centroids["LoanAmount"],c='red')
plt.xlabel('AnnualIncome')
plt.ylabel('Loan Amount (In Thousands)')
plt.show()

最全面的K-means聚类指南

这里,红点代表每个簇的3个质心。请注意,我们是随机选择了这些点,因此每次运行此代码时,你可能会得到不同的质心。

接下来,我们将定义一些条件来实现K-means聚类算法。我们先来看看代码:

# 第三步:将所有点分配给到某个质心距离最近的簇
# 第四步:重新计算新形成的簇的质心
# 第五步:重复第三步和第四步
diff = 1
j=0
while(diff!=0):
 XD=X
 i=1
 for index1,row_c in Centroids.iterrows():
 ED=[]
 for index2,row_d in XD.iterrows():
 d1=(row_c["ApplicantIncome"]-row_d["ApplicantIncome"])**2
 d2=(row_c["LoanAmount"]-row_d["LoanAmount"])**2
 d=np.sqrt(d1+d2)
 ED.append(d)
 X[i]=ED
 i=i+1
 C=[]
 for index,row in X.iterrows():
 min_dist=row[1]
 pos=1
 for i in range(K):
 if row[i+1] < min_dist:
 min_dist = row[i+1]
 pos=i+1
 C.append(pos)
 X["Cluster"]=C
 Centroids_new = X.groupby(["Cluster"]).mean()[["LoanAmount","ApplicantIncome"]]
 if j == 0:
 diff=1
 j=j+1
 else:
 diff = (Centroids_new['LoanAmount'] - Centroids['LoanAmount']).sum() + (Centroids_new['ApplicantIncome'] - Centroids['ApplicantIncome']).sum()
 print(diff.sum())
 Centroids = X.groupby(["Cluster"]).mean()[["LoanAmount","ApplicantIncome"]]

最全面的K-means聚类指南

每次运行时,这些值可能会有所不同。在这里,我们在两次迭代后质心没有变化时停止训练。我们最初将diff定义为1并且在while循环内部,我们将此diff计算为前一次迭代中的质心与当前迭代之间的差异。

当这个差异为0时,我们停止训练。现在让我们看看我们得到的簇:

color=['blue','green','cyan']
for k in range(K):
 data=X[X["Cluster"]==k+1]
 plt.scatter(data["ApplicantIncome"],data["LoanAmount"],c=color[k])
plt.scatter(Centroids["ApplicantIncome"],Centroids["LoanAmount"],c='red')
plt.xlabel('Income')
plt.ylabel('Loan Amount (In Thousands)')
plt.show()

最全面的K-means聚类指南

在这里,我们可以清楚地看到三个簇。红点代表每个簇的质心。我希望你现在能清楚地了解K-means的工作原理。

但是,在某些情况下,此算法效果可能不是很好。让我们来看看在使用K-means时你可能面临的一些挑战。

4. K-means聚类算法面临的挑战

使用K-means时我们面临的普遍挑战之一是簇的大小不同。假设我们有以下几点:
最全面的K-means聚类指南

与中心簇相比,左侧和最右侧的簇的点的数量比较少。现在,如果我们在这些点上应用K-means聚类,结果将是这样的:
最全面的K-means聚类指南

K-means的另一个挑战是当原始点的密度不同时。比如下面这些原始点:
最全面的K-means聚类指南

这里,红色簇中的点比较松散,而其余簇中的点紧密地堆积在一起。现在,如果我们在这些点上应用K-means,我们将得到这样的簇:
最全面的K-means聚类指南

我们可以看到紧凑的点已分配给同一个簇。而实际松散分布但在同一簇中的点却分配给不同的簇。效果并不理想,我们能做些什么呢?

其中一个解决方案是使用更多的簇进行划分。因此,在所有上述场景中,我们可以拥有更多的簇,而不是使用3个簇。也许设置k = 10可能会产生更有意义的簇。

还记得我们如何在K-means聚类中随机初始化质心吗?嗯,这也可能有问题,因为我们每次都可能得到不同的簇。因此,为了解决随机初始化的这个问题,有一种称为K-means ++的算法可用于为K-means选择初始值或初始簇质心。

5. K-means ++为K-means聚类选择初始簇质心

在某些情况下,如果簇的初始化不合适,K-means可能导致产生坏的簇。这就是K-means ++产生作用的地方。它指定了在使用标准K-means聚类算法向前推进之前初始化簇质心的过程。

使用K-means ++算法,我们优化了随机选择簇质心的步骤。在使用K-means ++初始化时,我们更有可能找到与最佳K-means解决方案竞争的解决方案。

使用K-means ++初始化质心的步骤是:

让我们举个例子来更清楚地理解这一点。假设我们有以下几点,我们想在这里划分3个簇:
最全面的K-means聚类指南

现在,第一步是随机选择一个数据点作为簇质心:
最全面的K-means聚类指南

假设我们选择绿点作为初始质心。现在,我们将使用此质心计算每个数据点与质心的距离(D(x)):
最全面的K-means聚类指南

下一个质心将是其平方距离(D(x)2)离当前质心最远的那个点:
最全面的K-means聚类指南

在这种情况下,红点将被选为下一个质心。现在,为了选择最后一个质心,我们将计算所有点到其最近的质心的距离,其中具有最大平方距离的点作为下一个质心:
最全面的K-means聚类指南

我们将选择最后一个质心为:
最全面的K-means聚类指南

初始化质心后,我们可以继续使用K-means算法。使用K-means ++初始化质心往往会改善聚类结果。虽然相对于随机初始化而言计算成本很高,但随后的K-means通常会更快地收敛。

我确信自本文开头以来你一直在想一个问题 :我们应该划分多少个簇?执行K-means时最佳簇的个数应该是多少?

6. 如何在K-means聚类中选择正确的簇的个数?

每个人在使用K-means时最常见的疑问之一就是如何选择合适数量的簇。

那么,让我们看看一种技术,它将帮助我们为K-means算法选择正确的簇的个数。我们来看看之前看到的客户细分示例。总而言之,该银行希望根据其收入和债务金额对客户进行细分:
最全面的K-means聚类指南

在这里,我们可以有两个簇,将客户分开,如下所示:
最全面的K-means聚类指南

所有低收入的客户都在一个簇中,而高收入的客户则在第二个簇中。我们还可以有4个簇:
最全面的K-means聚类指南

在这里,一个簇可能代表低收入和低债务的客户,其他簇是客户具有高收入和高负债等等。也可以有8个簇:
最全面的K-means聚类指南

老实说,我们可以拥有任意数量的簇。你能猜出可能的最大簇数是多少吗?我们想到将每个点分配给一个单独的簇。因此,在这种情况下,簇的数量将等于点数或观察数量。所以,

最大可能的簇数将等于数据集中的观察数。

但我们如何才能确定最佳簇数?我们可以做的一件事是绘制图形,其中x轴表示簇的数量,y轴将是评估度量。我们暂时说是Inertia 。

你也可以选择任何其他评估指标,如Dunn Index:
最全面的K-means聚类指南

接下来,我们将从一个小的簇值开始,比如说2使用2个簇训练模型,计算该模型的Inertia,最后将其绘制在上图中。假设我们得到Inertia大约为1000:
最全面的K-means聚类指南

现在,我们将增加簇的数量,再次训练模型,并绘制Inertia。这是我们得到的图:
最全面的K-means聚类指南

当我们将簇值从2更改为4时,Inertia急剧下降。随着我们进一步增加簇的数量,Inertia的下降变得缓慢并最终变得稳定。

Inertia的减小幅度变为常数时对应的簇的个数可以选择作为我们数据的正确簇的个数。

最全面的K-means聚类指南

在这里,我们可以选择6到10之间的任意数量的簇的个数。我们可以有7个,8个甚至9个簇。你还必须在确定簇的个数时查看计算成本。如果我们增加簇的数量,计算成本也会增加。因此,如果你没有高计算资源,我的建议是选择较少数量的簇。

现在让我们在Python中实现K-means聚类算法。我们还将看到如何使用K-means ++来初始化质心,并且还将绘制曲线以确定我们的数据集的正确簇的个数。

7. 在Python中实现K-means聚类

我们将致力于批发客户细分问题。你可以使用此链接[4]下载数据集。数据托管在UCI机器学习存储库中。

这个问题的目的是根据各种产品类别(如牛奶,杂货店,地区等)的年度支出对批发经销商的客户进行细分。让我们开始动手吧!

我们将首先导入所需的库:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
from sklearn.cluster import KMeans

接下来,让我们读取数据并查看前五行:

data=pd.read_csv("Wholesale customers data.csv")
data.head()

最全面的K-means聚类指南

我们有客户对于不同产品的消费细节,如牛奶,杂货,冷冻,洗涤剂等。现在,我们必须根据提供的细节细分客户。在此之前,让我们提取一些与数据相关的统计数据:

data.describe()

最全面的K-means聚类指南

在这里,我们看到数据的量纲存在很大差异。像Channel和Region这样的变量量纲很小,而Fresh,Milk,Grocery等变量量纲较大。

由于K-means是基于距离的算法,因此这种幅度差异可能会产生问题。因此,让我们首先将所有变量置于同一量纲下:

# 标准化数据
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
data_scaled = scaler.fit_transform(data)
# 统计标准化后的数据
pd.DataFrame(data_scaled).describe()

最全面的K-means聚类指南

现在看起来差不多了,接下来,让我们创建一个kmeans函数并将其拟合到数据上:

# 定义kmeans函数,并使用K-means++初始化
kmeans = KMeans(n_clusters=2, init='K-means++')
# 拟合标准化后的数据
kmeans.fit(data_scaled)

我们初始化了两个簇并注意到初始化在这里不是随机的。我们已经使用了K-means ++初始化,它通常会产生更好的结果,正如我们在前一节中所讨论的那样。

让我们评估形成的簇的好坏程度。为此,我们将计算簇的Inertia :

# 算法结束后的Inertia值
kmeans.Inertia_
Output: 2599.38555935614

我们的Inertia值接近2600.现在,让我们看看我们如何通过在Python中绘制曲线来确定的最佳簇数。我们将首先拟合多个K-means模型,我们将增加簇的数量。我们存储每个模型的Inertia值,然后绘制它以显示结果:

# 拟合多个K-means模型并将各个模型的Inertia值存储到空的列表中
SSE = []
for cluster in range(1,20):
 kmeans = KMeans(n_jobs = -1, n_clusters = cluster, init='K-means++')
 kmeans.fit(data_scaled)
 SSE.append(kmeans.Inertia_)
# 绘制图形
frame = pd.DataFrame({'Cluster':range(1,20), 'SSE':SSE})
plt.figure(figsize=(12,6))
plt.plot(frame['Cluster'], frame['SSE'], er='o')
plt.xlabel('Number of clusters')
plt.ylabel('Inertia')

最全面的K-means聚类指南

你能从这个图中分辨出最佳的簇的个数吗?观察上面的曲线,我们可以选择5到8之间的任意值作为簇的个数。让我们将聚类数设置为5并拟合模型:

kmeans = KMeans(n_jobs = -1, n_clusters = 5, init='K-means++')
kmeans.fit(data_scaled)
pred = kmeans.predict(data_scaled)

最后,让我们看一下上面形成的每个簇中的点的个数:

frame = pd.DataFrame(data_scaled)
frame['cluster'] = pred
frame['cluster'].value_counts()

最全面的K-means聚类指南

因此,有234个数据点属于簇4(索引3),然后是簇2(索引1)中的125个点,依此类推。这就是我们如何在Python中实现K-means聚类。

8. 结语

在本文中,我们讨论了一种最着名的聚类算法–K-means。我们从零开始逐步实现它。我们研究了在使用K-means时可能遇到的挑战,并了解了在初始化簇质心时K-means ++起到的作用。

最后,我们实现了K-means并通过绘制和观察曲线找到在K-means算法中的最佳簇数。

[1]: https://www.analyticsvidhya.com/blog/2019/04/introduction-image-segmentation-techniques-python/?utm_source=blog&utm_medium=comprehensive-guide-K-means-clustering

[2]: https://drive.google.com/file/d/1ZzEouo7lRJvajxK6jLM2K_p9xAwGw1tS/view?usp=sharing

[3]: https://datahack.analyticsvidhya.com/contest/practice-problem-big-mart-sales-iii/?utm_source=blog&utm_medium=comprehensive-guide-K-means-clustering

[4]: https://archive.ics.uci.edu/ml/machine-learning-databases/00292/Wholesale%20customers%20data.csv

本文采用「CC BY-SA 4.0 CN」协议转载自互联网、仅供学习交流,内容版权归原作者所有,如涉作品、版权和其他问题请给「我们」留言处理。

(0)
上一篇 2019-09-05 01:22
下一篇 2019-09-05 09:31

相关文章

关注我们
关注我们
分享本页
返回顶部