K-Clustering是什么意思?K-MeansClustering是最流行和使用最广泛的无监督学习模型。它也被称为聚类,因为它通过聚类数据来工作。与监督学习模型不同,无监督模型不使用标记数据。该算法的目的不是预测任何标签。相反,更好地理解数据集并对其进行标记。在k-means聚类中,我们将数据集聚类到不同的组中。这就是k-means聚类算法的工作原理(1)第一步是随机初始化一些点。这些点称为聚类质心。在上图中,红色和蓝色点是簇质心。您可以选择任意数量的聚类质心。但是聚类质心的数量必须小于数据点的总数。(2)第二步是集群分配步骤。在这一步中,我们需要遍历每个绿点。根据该点是更接近红色点还是蓝色点,我们需要将其分配给其中一个点。换句话说,根据它是在蓝色簇质心附近还是在红色簇质心附近,根据它是红色还是蓝色为绿色点着色。(3)下一步是移动簇质心。现在我们必须对分配给红色簇质心的所有红色点进行平均,并将红色簇质心移动到该平均值。我们需要对蓝色簇的质心做同样的事情。现在,我们有了新的簇质心。我们必须回到第2步(集群分配步骤)。我们需要将点重新排列到新的簇质心。之后重复三分之一。数字2和3需要重复几次,直到两个簇质心都位于正确的位置,如下图所示。看,我们只是根据分配给它们的簇质心为所有绿点着色。蓝色簇质心位于蓝色簇的中心,红色簇质心位于红色簇的中心。随着我们开发算法,它会变得更加清晰。我们将对此进行更详细的讨论。开发算法我将用于此算法的数据集是从AndrewNg在Coursera上的机器学习课程中获得的。以下是开发k-means算法的分步指南:(1)导入必要的包和数据集head()数据集只有两列。我采用了两个特色数据集,因为它很容易可视化。当您看到视觉效果时,您会更容易理解该算法。但是,相同的算法也适用于立方体。我正在将DataFramedf1转换为Numpy数组,因为我们将在此过程中处理其他数组:X=np.array(df1)现在我将按照上面讨论的三个步骤进行操作。(2)第一步是随机初始化质心。我将从数据集中随机初始化三个点。首先,我将选择0和数据集长度之间的三个数字。importrandomrandominit_centroids=random.sample(range(0,len(df1)),3)init_centroidsoutput:[95,30,17]使用这三个数字作为索引并获取这些索引的数据点。centroids=[]foriiininit_centroids:centroids.append(df1.loc[i])centroidsoutput:[03.90779315.094647Name:95,dtype:float64,02.66046615.196238Name:30,dtype:float64,03.00708914.6787978Name:4type]这三个点是我们的初始质心。我将它们转换成二维数组。因为这是我比较熟悉的格式。centroids=np.array(centroids)output:array([[3.90779317,5.09464676],[2.66046572,5.19623848],[3.00708934,4.67897758]])(3)实现集群分配步骤。在此步骤中,我们将遍历数据集中的所有数据点。一个数据点代表一行数据让我们看一行数据,看看它是如何分配给集群的。我们将计算所有三个质心的数据距离。然后将该数据点分配给距离最短的质心。如我们所见,我们必须计算两点之间的许多距离。让我们开发一个函数来计算距离。defcalc_distance(X1,X2):return(sum((X1-X2)**2))**0.5开发一个函数,将每个数据点分配给质心。我们的“centroids”数组只有三个值。所以我们有三个索引:0、1、2。我们将为每个数据点分配这些索引之一。deffindClosestCentroids(ic,X):assigned_centroid=[]foriinX:distance=[]forjinic:distance.append(calc_distance(i,j))assigned_centroid.append(np.argmin(distance))returnassigned_centroid这个函数是将数据点赋值给集群功能。让我们使用这个函数来计算每个数据点的质心:get_centroids=findClosestCentroids(centroids,X)get_centroids部分输出:[2,0,0,2,1,2,2,2,1,1,2,2,2,2,2,2,0,总输出很长。因此,我在这里显示部分输出。输出中的第一个质心是2,这意味着它被分配给质心列表的索引2。(4)最后一步是根据数据点的平均值移动质心。在此步骤中,我们将为每个质心取所有数据点的平均值,然后将质心移动到该平均值。例如,我们将在索引2处找到分配给质心的所有点的平均值,然后将质心2移动到平均值。对索引0和1处的质心执行相同的操作。让我们定义一个函数来执行此操作:defcalc_centroids(clusters,X):new_centroids=[]new_df=pd.concat([pd.DataFrame(X),pd.DataFrame(clusters),columns=['cluster'])],axis=1)forcinset(new_df['cluster']):current_cluster=new_df[new_df['cluster']==c][new_df.columns[:-1]]cluster_mean=current_cluster.mean(axis=0)new_centroids.append(cluster_mean)returnnew_centroids这些都是我们需要开发的函数。正如我之前讨论的那样,我们需要重复这个集群分配过程并多次移动质心,直到质心位于正确的位置。对于这个问题,我选择重复这个过程10次。我会在每次迭代后继续绘制质心和数据,以直观地向您展示它是如何工作的。foriinrange(10):get_centroids=findClosestCentroids(centroids,X)centroids=calc_centroids(get_centroids,X)#print(centroids)plt.figure()plt.scatter(np.array(centroids)[:,0],np.array(centroids)[:,1],color='black')plt.scatter(X[:,0],X[:,1],alpha=0.1)plt.show()五次迭代后,设置质心为它的最佳位置。因此,他们此后不会改变立场。我建议,在尝试降维之前,先运行上面的所有代码,让它学好。否则,您可能会感到不知所措!另外,既然我们已经详细解释了算法,那么我现在将加快执行速度。降维我想至少解释一下这个算法的一个用例。一个非常有用的用例是降维。想想图像。图像中可能有太多不同的像素。在任何计算机视觉问题中,如果我们能够缩小图片的尺寸,那么设备读取该图片的速度将会大大提高!难不成我们可以用刚才开发的算法来缩小图片的尺寸。我将使用一张青蛙的图片来说明这一点:>作者提供的图片我将这张图片上传到与笔记本相同的文件夹中。让我们导入这个:importcv2im=cv2.imread('frog.png')imoutput:array([[[2,57,20],[2,57,20],[2,57,21],...,[0,5,3],[8,12,11],[91,94,93]],[[2,56,20],[1,54,20],[1,56,19],...,[0,2,1],[7,9,8],[91,92,91]],[[2,55,20],[2,53,19],[1,54,18],...,[2,4,2],[8,11,9],[91,93,91]],...,[[6,76,27],[6,77,26],[6,78,28],...,[6,55,18],[13,61,25],[94,125,102]],[[9,79,31],[11,81,33],[12,82,32],...,[6,56,19],[14,61,27],[96,126,103]],[[43,103,63],[44,107,66],[46,106,66],...,[37,81,50],[47,88,59],[118,145,126]]],dtype=uint8)检查数组的形状,im.sgape输出:(155,201,3)我把整个数组除以255,这样所有的值都是从0到1。然后reshape为155*201x3,使其成为一个二维数组。因为我们之前已经开发了二维数组的所有功能。im=(im/255).reshape(155*201,3)正如你在上面看到的,有很多不同的像素值。我们将减少它并只保留10个像素值。让我们初始化10个随机索引,randomrandom_index=random.sample(range(0,len(im)),10)现在,像上一个示例一样找到质心:centroids=[]foriinrandom_index:centroids.append(im[i])centroids=np.array(centroids)输出:array([[0.00392157,0.21176471,0.06666667],[0.03529412,0.2627451,0.09803922],[0.29411765,0.3254902,0.26666667],[0.00784314,0.18431373,0.05882353],[0.29019608,0.49411765,0.28235294],[0.5254902,0.61176471,0.48627451],[0.04313725,0.23921569,0.09803922],[0.00392157,0.23529412,0.0745098],[0.00392157,0.20392157,0.04705882],[0.22352941,0.48235294,0.40784314]])现在,我也将"im"转换为数组,im=np.array(im)数据准备就绪。现在,我们可以继续聚类过程。但这一次,我不打算进行可视化。因为数据不再是二维的。因此,可视化并不容易。foriinrange(20):get_centroids=findClosestCentroids(centroids,im)centroids=calc_centroids(get_centroids,im)我们现在得到更新的质心。centroids输出:[00.01772610.22736020.084389dtype:float64,00.11979110.38588220.247633dtype:float64,00.15511710.49205120.331497dtype:float64,00.00621710.04859620.019410dtype:float64,00.25828910.55329020.406759dtype:float64,00.72816710.76461020.689944dtype:float64,00.07351910.31851320.170943dtype:float64,00.03511610.27366520.114766dtype:float64,00.01081010.14462120.053192dtype:float64,00.44419710.61778020.513234dtype:float64]这是最后一步。Wewillonlykeepthese10points.如果您还打印get_centroids,您将看到集群分配。现在我们要遍历整个数组“im”并将数据更改为其对应的簇质心值。这样我们将只有这些质心值。我不想更改原始数组,而是复制一份并在那里进行更改。imim_recovered=im.copy()foriinrange(len(im)):im_recovered[i]=centroids[get_centroids[i]]你还记得吗,我们一开始就改变了图像的尺寸,让它成为一个二维数组。我们现在需要将它改回原来的形状。im_recoveredim_recovered=im_recovered.reshape(155,201,3)在这里,我将并排绘制原始图像和缩小图像以显示差异:im1=cv2.imread('frog.png')importmatplotlib.imageasmpimgfig,ax=plt.subplots(1,2)ax[0].imshow(im1)ax[1].imshow(im_recovered)>ImagebyAuthor看,我们把图像的尺寸缩小了这么多。不过,它看起来像一只青蛙!但是电脑会读得更快!结论在本文中,我解释了k-means聚类的工作原理以及如何从头开始开发k-means聚类算法。我还解释了如何使用此算法来减小图像大小。请尝试其他图片。这是我在本文中使用的数据集的链接。https://github.com/rashida048/Machine-Learning-With-Python/blob/master/kmean.xlsx这是代码:https://github.com/rashida048/Machine-Learning-With-Python/blob/主人/k_mean_clustering_final.ipynb
