精华内容
下载资源
问答
  • Kmeans聚类算法详解

    万次阅读 多人点赞 2018-05-16 18:41:40
    摘要:本文通过图文详细介绍Kmeans聚类算法原理和程序实现,以及如何选取类簇中心点。本文首先介绍利用该算法的原理及理解,详细介绍基于MATLAB设计一个自定义的Kmeans函数过程,然后利用该函数对UCI的数据集进行...

    摘要:本文详细介绍Kmeans聚类算法的原理和程序实现。首先介绍利用该算法的原理及理解,详细介绍基于MATLAB设计一个自定义的Kmeans函数过程,然后利用该函数对UCI的数据集进行聚类以测试聚类结果。后续章节将介绍的主要部分有:

    • Kmeans算法的原理及理解
    • 编程实现
    • 聚类结果评价
    • 类簇中心点的选取

    点击下载:本文Kmeans算法M函数及测试完整文件


    1. 前言

    作为无监督聚类算法中的代表——K均值聚类(Kmeans)算法,该算法的主要作用是将相似的样本自动归到一个类别中。所谓的监督算法,就是输入样本没有对应的输出或标签。聚类(clustering)试图将数据集中的样本划分为若干个通常是不相交的子集,每个子集称为一个“簇(cluster)”,聚类既能作为一个单独过程,用于找寻数据内在的分布结构,也可作为分类等其他学习任务的前去过程。——《Machine Learning》

    聚类算法也许是机器学习中“新算法”出现最多、最快的领域,一个重要的原因是聚类不存在客观标准,给定数据集总能从某个角度找到以往算法未覆盖的某种标准从而设计出新算法。Kmeans算法十分简单易懂而且非常有效,但是合理的确定K值和K个初始类簇中心点对于聚类效果的好坏有很大的影响。众多的论文基于此都提出了各自行之有效的解决方案,新的改进算法仍然不断被提出,此类文章大家可以在Web Of Science中搜索。

    尽管Kmeans算法在MATLAB、Python等语言的工具箱函数中都有自带的函数可供调用,但作为机器学习的研究者新来说要设计出新的算法,有时就得“定制”自己的Kmeans函数了。自己动手编写无疑也更加能理解算法的具体过程,接下来就让我们进入正题吧


    2. Kmeans算法的原理与理解

    Kmeans算法是最常用的聚类算法,主要思想是:在给定K值和K个初始类簇中心点的情况下,把每个点(亦即数据记录)分到离其最近的类簇中心点所代表的类簇中,所有点分配完毕之后,根据一个类簇内的所有点重新计算该类簇的中心点(取平均值),然后再迭代的进行分配点和更新类簇中心点的步骤,直至类簇中心点的变化很小,或者达到指定的迭代次数。

    2.1 基本原理

    假定给定数据样本X,包含了n个对象X={X1,X2,X3,...,Xn}X=\left \{ X_{1} ,X_{2},X_{3},...,X_{n}\right \},其中每个对象都具有m个维度的属性。Kmeans算法的目标是将n个对象依据对象间的相似性聚集到指定的k个类簇中,每个对象属于且仅属于一个其到类簇中心距离最小的类簇中。对于Kmeans,首先需要初始化k个聚类中心{C1,C2,C3,...,Ck},1<kn\left \{ C_{1} ,C_{2},C_{3},...,C_{k}\right \},1<k\leq n,然后通过计算每一个对象到每一个聚类中心的欧式距离,如下式所示dis(Xi,Cj)=t=1m(XitCjt)2dis(X_{i},C_{j})=\sqrt{\sum_{t=1}^{m}(X_{it}-C_{jt})^{2}}
    上式中,XiX_{i}表示第i个对象1in1\leq i\leq n,CjC_{j}表示第j个聚类中心的1jk1\leq j\leq kXitX_{it}表示第i个对象的第t个属性,1tm1\leq t\leq mCjtC_{jt}表示第j个聚类中心的第t个属性。

    依次比较每一个对象到每一个聚类中心的距离,将对象分配到距离最近的聚类中心的类簇中,得到k个类簇{S1,S2,S3,...,Sk}\left \{ S_{1},S_{2},S_{3},...,S_{k} \right \}

    Kmeans算法用中心定义了类簇的原型,类簇中心就是类簇内所有对象在各个维度的均值,其计算公式如下Ct=XiSlXiSlC_{t}=\frac{\sum_{X_{i}\in S_{l}}X_{i}}{\left | S_{l} \right |}
    式中,ClC_{l}表示第l个聚类的中心,1lk1\leq l\leq kSl\left | S_{l} \right |表示第l个类簇中对象的个数,XiX_{i}表示第l个类簇中第i个对象,1iSl1\leq i\leq\left | S_{l} \right |

    2.2 算法流程

    输入:样本集D={x1,x2,x3,...,xm}D=\left \{ x_{1},x_{2},x_{3},...,x_{m} \right \};聚类簇数k.
    过程:
    1:从D中随机选择k个样本作为初始均值向量{μ1,μ2,μ3,...,μk}\left \{ \mu _{1},\mu _{2},\mu _{3},...,\mu _{k} \right \}

    2:repeat
    3: 令Ci=(1ik)C_{i}=\varnothing (1\leqslant i\leqslant k)
    4: for j=1,2,…,m do
    5: 计算样本xjx_{j}与各均值向量μi(1ik)\mu_{i}(1\leqslant i\leqslant k)的距离:dji=xjμi2d_{ji}=\left \| x_{j}-\mu_{i} \right \|_{2};
    6: 根据距离最近的均值向量确定xjx_{j}的簇标记:λj=argmini{1,2,3,...,k}dji\lambda _{j}=arg min_{i\in \left \{ 1,2,3,...,k \right \}}d_{ji}
    7: 将样本xjx_{j}划入相应的簇:Cλj=Cλj{xj}C_{\lambda_{j}}=C_{\lambda_{j}}\cup \left \{ x_{j} \right \};
    8: end for

    9: for i=1,2,…,k do
    10: 计算新均值向量:μi=1CixCix\mu_{i}^{'}=\frac{1}{\left | C_{i} \right |}\sum _{x\in C_{i}}x;
    11: if μiμi\mu_{i}^{'}\neq \mu_{i} then
    12: 将当前均值向量 μi\mu_{i}更新为μi\mu_{i}^{'}
    13: else
    14: 保持当前均值不变
    15: end if

    16: end for
    17:until 当前均值向量均未更新
    输出:簇划分C={C1,C2,...,Ck}C=\left \{ C_{1} ,C_{2},...,C_{k} \right \}

    以上算法流程引自周志华《机器学习》,从流程来看K-means算法计算步骤基本上可以概括为两个部分:(1)计算每一个对象到类簇中心的距离;(2)根据类簇内的对象计算新的簇类中心。


    3. 编程实现

    为了方便应用我们将其编写为一个M函数KMeans(),首先需要确定函数的输入输出。这里输入参数为:data,K,iniCentriods,iterations(其中data为输入的不带标号的数据集数据矩阵,大小为numOfDatanumOfAttributes,K为数据分的类簇数目,iniCentriods为自行指定的初始聚类中心矩阵,大小为KnumOfAttributes,iterations为算法迭代次数。)
    输出参数为:Idx,centroids,DistanceIdx为返回的分类标号, centroids为每一类的中心,Distance为类内总距离)

    根据前面2.2节中的算法流程编写Kmeans算法的MATLAB程序如下

    %% Kmeans算法
    % 输入:
    % data 输入的不带分类标号的数据
    % K 数据一共分多少类
    % iniCentriods 自行指定初始聚类中心
    % iterations 迭代次数
    
    % 输出:
    % Idx 返回的分类标号
    % centroids 每一类的中心
    % Distance 类内总距离
    
     
    function [Idx,centroids,Distance]=KMeans(data,K,iniCentriods,iterations)
    [numOfData,numOfAttr]=size(data); % numOfData是数据个数,numOfAttr是数据维数
    centroids=iniCentriods;
    %% 迭代
    for iter=1:iterations
        pre_centroids=centroids;% 上一次求得的中心位置
        
        tags=zeros(numOfData,K);
        %% 寻找最近中心,更新中心
        for i=1:numOfData
            D=zeros(1,K);% 每个数据点与每个聚类中心的标准差
            Dist=D;
            
            % 计算每个点到每个中心点的标准差
            for j=1:K
                Dist(j)=norm(data(i,:)-centroids(j,:),2);
            end
            
            [minDistance,index]=min(Dist);% 寻找距离最小的类别索引
            tags(i,index)=1;% 标记最小距离所处的位置(类别)
        end
        
        
        %% 取均值更新聚类中心点
        for i=1:K
            if sum(tags(:,i))~=0
                % 未出现空类,计算均值作为下一聚类中心
                for j=1:numOfAttr
                    centroids(i,j)=sum(tags(:,i).*data(:,j))/sum(tags(:,i));
                end
            else % 如果出现空类,从数据集中随机选中一个点作为中心
                randidx = randperm(size(data, 1));
                centroids(i,:) = data(randidx(1),:);
                tags(randidx,:)=0;
                tags(randidx,i)=1;
            end
        end
        
       
        if sum(norm(pre_centroids-centroids,2))<0.001  % 不断迭代直到位置不再变化
            break;
        end
        
        
    end
    
    %% 计算输出结果
    Distance=zeros(numOfData,1);
    Idx=zeros(numOfData,1);
    for i=1:numOfData
        D=zeros(1,K);% 每个数据点与每个聚类中心的标准差
        Dist=D;
        % 计算每个点到每个中心点的标准差
        for j=1:K
            Dist(j)=norm(data(i,:)-centroids(j,:),2);
        end
        
        [distance,idx]=min(Dist);% 寻找距离最小的类别索引
        distance=Dist(idx);
        
        Distance(i)=distance;
        Idx(i)=idx;
    end
    Distance=sum(Distance,1);% 计算类内总距离
    end
    

    在以上代码中其最主要部分在于第18至58行,进行寻找最近中心和求取均值更新聚类中心点。值得注意的是,在聚类过程中可能会出现空类即代码第44行那样,为保证算法的继续运行,从数据集中随机选取一个点作为中心。

    4. 聚类结果评价

    为了验证编写的Kmeans函数的性能,这里对想用的UCI数据集Iris数据集进行聚类并计算聚类的准确率,Iris数据集可以在http://archive.ics.uci.edu/ml/index.php上下载得到。首先读取Iris数据集,自行指定初始聚类中心调用前面编写的KMeans函数进行聚类,然后计算聚类的准确率,其代码如下

    clear 
    data=load('Iris.txt');
    data=data(:,2:end);
    
    matrix=[5.9016,2.7484,4.3935,1.4339;6.8500,3.0737,5.7421,2.0711;5.0060,3.4280,1.4620,0.2460];
    [Idx,C,distance]=KMeans(data,3,matrix,500);
    Distance=sum(distance)
    
    c1=Idx(1:50,1);c2=Idx(51:100,1);c3=Idx(101:150,1);
    accuracy=(sum(c1==mode(Idx(1:50,1)))+sum(c2==mode(Idx(51:100,1)))+sum(c3==mode(Idx(101:150,1))))/150
    

    为方便使用Iris数据集经过了一些整理,这里将最后一列的带字符串的标签Iris-setosa,Iris-versicolor,Iris-virginica分别用数字1,2,3代替并移到了第一列,所以第三行选取的是从第二列至最后一列的数据。第5行中的matrix是查阅论文得到的一个初始聚类中心,正好用来比对聚类结果。第6行则调用KMeans()函数进行聚类,得到聚类标号和类内距离。对每类的类内距离求和即得到总的距离Distance,如第7行。准确率的计算有点麻烦,因为不能直接用KMeans计算后得到的标号跟原数据集中的标号对比计算准确率,KMeans只需要也只能将那些“相似”的数据点聚集到一类中,而给这一类数据的标号却是可能跟原数据集不同的。

    这里采用一个简单的方法,从原数据集的标签可以看出第1-50个数据点为一类(Iris-setosa),第51-100为一类(Iris-versicolor),第101-150为一类(Iris-virginica),因此只需确定每50个数据点中的聚类标号是不是一致。取它们之中数目最多的标号作为正确的个数,最终比上数据集的总数即为准确率。以上代码运行结果如下所示。

    5. 类簇中心点的选取

    KMeans算法本身思想比较简单,但是合理的确定K值和K个初始类簇中心点对于聚类效果的好坏有很大的影响。最简单的确定初始类簇中心点的方法是随机产生数据大小范围内的K个点作为初始的簇类中心点。随机产生初始点并进行测试的程序代码如下

    clear
    data=load('Iris.txt');
    data=data(:,2:end);
    K=3;
    
    
    %% 产生随机初始点
    [numOfData,numOfAttr]=size(data);   % numOfData是数据个数,numOfAttr是数据维数
    
    centroids=zeros(K,numOfAttr);       % 随机初始化,最终迭代到每一类的中心位置
    maxAttr=zeros(numOfAttr);        % 每一维最大的数
    minAttr=zeros(numOfAttr);        % 每一维最小的数
    for i=1:numOfAttr
        maxAttr(i)=max(data(:,i));    % 每一维最大的数
        minAttr(i)=min(data(:,i));    % 每一维最小的数
        for j=1:K
            centroids(j,i)=maxAttr(i)+(minAttr(i)-maxAttr(i))*rand();  % 随机初始化,选取每一维[min max]中初始化
        end
    end
    
    [Idx,C,distance]=KMeans(data,K,centroids,500);% 调用KMeans
    Distance=sum(distance)% 计算类内距离之和
    
    %% 计算准确率
    c1=Idx(1:50,1);c2=Idx(51:100,1);c3=Idx(101:150,1);
    Accuracy=(sum(c1==mode(Idx(1:50,1)))+sum(c2==mode(Idx(51:100,1)))+sum(c3==mode(Idx(101:150,1))))/numOfData
    

    可以多运行几次以上代码,可以看出由于初始点事随机选取的每次运行得到的结果有所差异。这也是基本Kmeans算法的一个缺点,随着众多改进算法的提出Kmeans算法的这一问题也得到改善,深入了解的朋友可以查阅相关论文。

    6. 结束语

    本博文的完整MATLAB程序文件与整理好的数据集文件已经上传,下载即可运行。下载地址如下

    点击下载:本文Kmeans算法M函数及测试完整文件

    公众号获取
        本人微信公众号已创建,扫描以下二维码并关注公众号“AI技术研究与分享”,后台回复“KM20180516”即可获取全部资源文件信息。

    由于编者能力有限,代码即使经过了多次校对,也难免会有疏漏之处。希望您能热心指出其中的错误,以便下次修改时能以一个更完美更严谨的样子,呈现在大家面前。同时如果有更好的实现方法也请您不吝赐教。

    展开全文
  • k-means算法是非监督聚类最常用的一种方法,因其算法简单和很好的适用于大样本数据,广泛应用于不同领域,本文详细总结了k-means聚类算法原理 。目录1. k-means聚类算法原理2. k-means聚类算法步骤3. k-means++聚类...

    k-means算法是非监督聚类最常用的一种方法,因其算法简单和很好的适用于大样本数据,广泛应用于不同领域,本文详细总结了k-means聚类算法原理 。

    目录

    1. k-means聚类算法原理

    2. k-means聚类算法步骤

    3. k-means++聚类优化算法

    4. 小批量处理的k-means聚类算法

    5. k值的选取

    6. k-means聚类算法不适用的几个场景

    7. k-means与knn区别

    8. 小结

    1. k-means聚类算法原理

    聚类算法性能度量的文章提到若簇类相似度好簇间的相似度差,则聚类算法的性能较好。我们基于此定义k-means聚类算法的目标函数:

    63b9d9153a47c91e7e099e625d62ca29.png 

    其中d1f4c11b138863395759dda1bb03783d.png表示当样本252e90c4f230a2119cbb3207d9d01be7.png划分为簇类k时为1,否则为0。

    d3eebaab4e52d2846524472b9581b618.png

    4e182acc6c80957df928787d778e29a8.png表示簇类k的均值向量。

    目标函数(1.1)在一定程度上刻画了簇内样本围绕簇均值向量的紧密程度,J值越小则簇内样本相似度越高。最小化目标函数是一个NP难题,k-means聚类运用EM算法思想实现模型的最优化

    1)初始化K个簇的均值向量,即48abfee5659bc3eb8f90bfa8bc10a830.png是常数,求J最小化时的d1f4c11b138863395759dda1bb03783d.png。我们不难知道当数据点划分到离该数据点最近的簇类时,目标函数J取最小。

    2)已知d1f4c11b138863395759dda1bb03783d.png,求最小化J时相应的4e182acc6c80957df928787d778e29a8.png。令目标函数J对4e182acc6c80957df928787d778e29a8.png的偏导数等于0:

    030428cede2d35af74e060b1f5d60cb9.png

    得:

    4e100f79251b9179dc42c2d18bc19a96.png

    4e182acc6c80957df928787d778e29a8.png表达式的含义是簇类中心等于所属簇类样本的均值。

    本节用EM算法思想解释了k-means聚类算法的参数更新过程,相信大家对k-means聚类算法有一个更清晰的认识。

    2. k-means聚类算法步骤

    k-means聚类算法步骤实质是EM算法的模型优化过程,具体步骤如下:

    1)随机选择k个样本作为初始簇类的均值向量;

    2)将每个样本数据集划分离它距离最近的簇;

    3)根据每个样本所属的簇,更新簇类的均值向量;

    4)重复(2)(3)步,当达到设置的迭代次数或簇类的均值向量不再改变时,模型构建完成,输出聚类算法结果。

    3. k-means++聚类优化算法

    若给定足够的迭代次数,k-means算法就能收敛,但是有可能在局部最小值点收敛。k-means收敛局部极值的原因很可能是初始化簇类中心的距离很接近,而且算法的收敛时间也加长了,为了避免这一情况,多次运行k-means聚类算法,每次运行初始化不同的簇类中心。

    另一种解决k-means收敛局部极值的方法是k++聚类算法,k-means++通过让簇间中心互相远离的方案来初始化簇类中心。

    具体算法步骤:

    1)随机选择一个样本数据作为第一个簇类中心573c9998a27187214bbd0d8444085e08.png

    2)计算每一个样本057c3d56704317f343cd06037e1356c1.png到簇类中心61eb0fd1516b3463140d36f19eb06b48.png的最小距离;

    8d4c882671568f47ed34f470dc546b15.png

    3)选择最大距离的样本点作为簇类中心;

    4)重复(2)(3),直到达到簇类个数k;

    5)利用这k个簇类中心作为初始化的簇类中心运行k-means算法;

    4. 小批量处理的k-means聚类算法

    k-means聚类算法的时间复杂度随着样本数的增加而增大,若样本量达到上万时,k-means聚类算法非常耗时,因此对该数据集进行无放回随机抽样得到合适的小批量样本数据集,sklearn.cluster包提供了相应的实现方法MiniBatchKMeans。

    小批量处理的k-means聚类算法在减少了收敛时间的同时,算法结果相差不大。如下结果用inertia评价k-means和MiniBatchKmeans的算法结果。

    import timeimport numpy as npimport matplotlib.pyplot as pltfrom sklearn.cluster import MiniBatchKMeans, KMeansfrom sklearn.metrics.pairwise import pairwise_distances_argminfrom sklearn.datasets.samples_generator import make_blobs# Generate sample datanp.random.seed(0)# minibatch随机抽样100例样本进行训练batch_size = 100centers = [[1, 1], [-1, -1], [1, -1]]n_clusters = len(centers)# 产生3个簇类的30000个样本数据X, labels_true = make_blobs(n_samples=30000, centers=centers, cluster_std=0.7)# k-means++算法k_means = KMeans(init='k-means++', n_clusters=3, n_init=10)t0 = time.time()k_means.fit(X)

    t_batch = time.time() - t0

    # MiniBatchKMeans算法mbk = MiniBatchKMeans(init='k-means++', n_clusters=3, batch_size=batch_size,n_init=10, max_no_improvement=10, verbose=0)t0 = time.time()mbk.fit(X)t_mini_batch = time.time() - t0# 打印k-means++运行时间和性能度量print("k-means++_runtime= ",t_batch)print("k_means++_metics= ",k_means.inertia_)# 打印minibatch_k_means++运行时间和性能度量值print("MiniBatch_k_means++_runtime= ",t_mini_batch)print("k_means_metics= ",mbk.inertia_)#>k-means++_runtime= 0.36002039909362793k_means++_metics= 25164.97821695812MiniBatch_k_means++_runtime= 0.15800929069519043k_means_metics= 25178.611517320118

    图形结果表示:

    a6e142ffa860bb7c8dd6f52c7e0bda63.png

    5. 簇类个数k的选取

    我们运用Calinski-Harabasz分数作为评价聚类性能的标准,分数越大,聚类性能越好,Calinski-Harabasz的含义请参考该文

    我们首先构建四个不同标准差的二维样本数据:

    from sklearn import metrics# 定义四个簇类中心centers1 = [[0,0],[1, 1],[1.9, 2],[3, 3]]# 定义每个簇类的标准差std1 = [0.19,0.2,0.3,0.4]# 算法可重复性seed1 =45# 产生4个簇类的30000个样本数据X, labels_true = make_blobs(n_samples=30000, centers=centers1, cluster_std=std1,random_state=seed1)plt.scatter(X[:,0],X[:,1],marker='o')plt.show()

    数据散点图如下:

    ee7614f07fd9fb40659c9b8b94624b96.png

    首先选择簇类个数为2,即K=2,查看聚类效果图和Calinski-Harabasz分数。

    # 若我们选择k=2k_means = KMeans(init='k-means++', n_clusters=2, n_init=10,random_state=10)y_pred = k_means.fit_predict(X)plt.scatter(X[:, 0], X[:, 1], c=y_pred)plt.show()scores2 = metrics.calinski_harabaz_score(X,y_pred)print("the Calinski-Harabasz scores(k=2) is: ",scores2)

    散点图效果:

    73d8063ec34a6431c4432ae74f550ffd.png

    Calinski-Harabasz分数:

    #> the Calinski-Harabasz scores(k=2) is:  85059.39875951338

    选择簇类个数为3,即K=3,查看聚类效果图和Calinski-Harabasz分数。

    散点图效果:

    92a08414ab86123b713d47fb86880c61.png

    Calinski-Harabasz分数:

    #> the Calinski-Harabasz scores(k=3) is:  92778.08155077342

    选择簇类个数为4,即K=4,查看聚类效果图和Calinski-Harabasz分数。

    散点图效果:

    b38feca160057b73f3e3c72f144ef8c7.png

    Calinski-Harabasz分数:

    #> the Calinski-Harabasz scores(k=4) is:  158961.98176157777

    有结果可知:k=4时的Calinski-Harabasz分数最高,因此选择簇类个数为4 。

    6. k-means聚类算法不适用的几个场景

    k_means算法假设数据是各向同性的,即不同簇类的协方差是相等的,通俗讲就是样本数据落在各个方向的概率是相等的。

    1)若样本数据是各向异性的,那么k-means算法的效果较差。

    生成一组各向异性的样本数据:

    import numpy as npimport matplotlib.pyplot as pltfrom sklearn.cluster import KMeansfrom sklearn.datasets import make_blobsplt.figure(figsize=(6, 6))n_samples = 1500random_state = 170X, y = make_blobs(n_samples=n_samples, random_state=random_state)# 生成各项异性的数据transformation = [[0.60834549, -0.63667341], [-0.40887718, 0.85253229]]X_aniso = np.dot(X, transformation)plt.scatter(X_aniso[:, 0], X_aniso[:, 1], marker='.')plt.title("Anisotropicly Distributed Blobs")plt.show()

    生成样本数据的散点图效果:

    cafdeb8d0d61030808245bfdcb5f4b4a.png

    根据散点图分布,我们用簇类数k=3训练样本数据:

    # k =3训练数据,输出散点效果图y_pred = KMeans(n_clusters=3, random_state=random_state).fit_predict(X_aniso)plt.scatter(X_aniso[:, 0], X_aniso[:, 1], marker='.',c=y_pred)plt.title("clustering scatter distributed k=3")plt.show()

    聚类效果图:

    24c4091479f4d04d78784d8d6b0994fc.png

    由上图可知聚类效果很差。

    2)当样本数据集是非凸数据集时,k-means聚类效果较差

    首先生成非凸数据集:

    # 非凸数据集plt.figure(figsize=[6,6])from sklearn import cluster,datasetsn_samples = 1500noisy_circles = datasets.make_circles(n_samples=n_samples, factor=.5, noise=.05)plt.scatter(noisy_circles[0][:,0],noisy_circles[0][:,1],marker='.')plt.title("non-convex datasets")plt.show()

    散点图效果:

    5266acadd6c692c8f4fe861f78be3956.png

    根据散点图分布,我们用簇类数k=2训练样本数据:

    # k=2训练数据y_pred = KMeans(n_clusters=2, random_state=random_state).fit_predict(noisy_circles[0])plt.scatter(noisy_circles[0][:, 0], noisy_circles[0][:, 1], marker='.',c=y_pred)plt.title("non-convex k-means clustering")plt.show()

    散点图聚类效果:

    12bf6f1c6e3e37228f7dc1660b3e49e5.png

    由上图可知聚类效果很差。

    3)当训练数据集各个簇类的标准差不相等时,k-means聚类效果不好。

    # 构建不同方差的各簇类数据,标准差分别为1.0,2.5,0.5X_varied, y_varied = make_blobs(n_samples=n_samples,cluster_std=[1.0, 2.5, 0.5],random_state=random_state)y_pred = KMeans(n_clusters=3, random_state=random_state).fit_predict(X_varied)plt.scatter(X_varied[:, 0], X_varied[:, 1], c=y_pred)plt.title("Unequal Variance")plt.show()

    由下图可知聚类效果不好:

    2719d5818a8145b2497d336b0253b99a.png

    4)若各簇类的样本数相差比较大,聚类性能较差。

    产生三个样本数分别为500,10,10的簇类:

    n_samples = 1500random_state = 170# 产生三个簇类,每个簇类样本数是500X, y = make_blobs(n_samples=n_samples, random_state=random_state)# 三个簇类的样本数分别为500,100,10,查看聚类效果X_filtered = np.vstack((X[y == 0][:500], X[y == 1][:100], X[y == 2][:5]))plt.scatter(X_filtered[:, 0], X_filtered[:, 1], marker='.')plt.title("Unequal Variance")plt.show()

    散点图分布:

    e32c8b58de45e4d09a0ea92b193ce419.png

    运用k-means对其聚类:

    y_pred = KMeans(n_clusters=3,random_state=random_state).fit_predict(X_filtered)plt.scatter(X_filtered[:, 0], X_filtered[:, 1], c=y_pred,marker='.')plt.title("Unevenly Sized Blobs")plt.show()

    效果图如下:

    572cfe3cd09c45affde26593f7f66c92.png

    5) 若数据维度很大时,运行时间很长,可以考虑先用pca降维。

    # 产生100维的15000个样本n_samples = 15000random_state = 170plt.figure(figsize=[10,6])t0=time.time()# 产生三个簇类,每个簇类样本数是500X, y = make_blobs(n_samples=n_samples, n_features=100,random_state=random_state)y_pred = KMeans(n_clusters=3,random_state=random_state).fit_predict(X)t1 =time.time()-t0scores1 = metrics.calinski_harabaz_score(X,y)print("no feature dimonsion reduction scores = ",scores1)print("no feature dimonsion reduction runtime = ",t1)

    输出聚类效果和运行时间

    no feature dimonsion reduction scores =  164709.2183791984no feature dimonsion reduction runtime =  0.5700197219848633

    数据先进行PCA降维再用k-means聚类,

    # 数据先pca降维,再k-means聚类from sklearn.decomposition import PCApca = PCA(n_components=0.8)s=pca.fit_transform(X)t0=time.time()y_pred = KMeans(n_clusters=3,random_state=random_state).fit_predict(s)t1 =time.time()-t0print("feature dimonsion reduction scores = ",scores1)print("feature dimonsion reduction runtime = ",t1)

    输出聚类效果和运行时间:

    feature dimonsion reduction scores =  164709.2183791984feature dimonsion reduction runtime =  0.0630037784576416

    由结果对比可知,聚类效果相差无几的情况下,运行时间大大降低了。

    7. k-means与knn的区别

    k-means是最简单的非监督分类算法,knn是最简单的监督分类算法,初学者学完监督学习章节再去学非监督章节会感觉似曾相识,原因可能都是用距离作为评价样本间的相似度。下面列举几个区别的地方:

    1)knn是监督学习方法,k-means是非监督学习方法,因此knn需要样本的标记类,k-means不需要;

    2)knn不需要训练,只要找到距离测试样本最近的k个样本,根据k个样本的类别给出分类结果;k-means需要训练,训练的目的是得到每个簇类的均值向量(质心),根据质心给出测试数据的分类结果;

    8. 小结

    k-means算法简单且在一些大样本数据表现较好而得到广泛的应用,本文也列举了k-means不适用的几个场景,其他聚类算法可能很好的解决k-means所不能解决的场景,不同的聚类算法有不同的优缺点,后续文章会持续介绍聚类算法,希望这篇k-means总结文章能帮到您。

    参考

    https://scikit-learn.org/stable/modules/clustering.html#clustering

    https://www.cnblogs.com/pinard/p/6169370.html

    推荐阅读

    聚类 | 超详细的性能度量和相似度方法总结

    cd163990dbf4ebde48c7bcffb38a8b05.png

    展开全文
  • Kmeans聚类算法原理与实现

    千次阅读 2016-07-11 15:07:52
    1 Kmeans聚类算法的基本原理 K-means算法是最为经典的基于划分的聚类方法,是十大经典数据挖掘算法之一。K-means算法的基本思想是:以空间中k个点为中心进行聚类,对最靠近他们的对象归类。通过迭代的方法,逐次...

    Kmeans聚类算法

    1 Kmeans聚类算法的基本原理

    K-means算法是最为经典的基于划分的聚类方法,是十大经典数据挖掘算法之一。K-means算法的基本思想是:以空间中k个点为中心进行聚类,对最靠近他们的对象归类。通过迭代的方法,逐次更新各聚类中心的值,直至得到最好的聚类结果。

    假设要把样本集分为k个类别,算法描述如下:

      (1)适当选择k个类的初始中心,最初一般为随机选取;

      (2)在每次迭代中,对任意一个样本,分别求其到k个中心的欧式距离,将该样本归到距离最短的中心所在的类;

      (3)利用均值方法更新该k个类的中心的值;

      (4)对于所有的k个聚类中心,重复(2)(3),类的中心值的移动距离满足一定条件时,则迭代结束,完成分类。

    Kmeans聚类算法原理简单,效果也依赖于k值和类中初始点的选择。

    2 算法结构与实现方法

    Kmeans算法相对比较简单,本次算法实现采用C++语言,作为面向对象设计语言,为保证其良好的封装性以及代码重用性。软件包含三个部分,即kmeans.hkmeans.cppmain.cpp

    kmeans.h中,首先定义一个类,class KMeans,由于本算法实现需要对外部数据进行读取和存储,一次定义了一个容器Vector,其中数据类型为结构体st_point,包含三维点坐标以及一个char型的所属类的ID。其次为函数的声明。

    4.1 程序基本机构与对应函数

    kmeans.cpp中具体给出了不同功能的公有函数,如图_1中所示,函数比较细化,便于后期应用的扩展,比较具体是聚类函数:cluster,其中严格根据kmeans基本原理,聚类的相似度选用的是最简单的欧式距离,而迭代的结束判定条件选用两次中心值之间的偏差是否大于给定Dist_near_zero值。具体参见程序源代码。

    3 数据描述

    本次算法实验采用数据为三维点云数据,类似于实验室中三维激光扫描仪器所采得数据,形式上更为简单,整齐有规律,在cloudcompare中显示出来,如下图:

    4.2 数据原始图

    数据为三维坐标系下的三个点云集,分别为球体,园面以及正方体,而test.txt文件中是一组三维的点集,是混乱的,聚类算法要做的便是将其中分类存储起来。很自然的,聚类中K值选择了3

    在软件实现时,建立了一个含有结构体类型的容器,对原始数据进行读取。

    typedef struct st_point 
    
    { st_pointxyz pnt; //st_pointxyz 为三维点结构类型数据 stru st_pointxyz 
    
    int groupID; 
    
        st_point () { } 
    
        st_point(st_pointxyz &p, int id) 
    
        {pnt = p; 
    
         groupID = id; 
    
        } 
    
    }st_point; 
    

    该数据结构类型中包含三维点数据以及所分类的ID,数据容器为vector<st_point>

    4 算法描述与源码分析

    本节重点分析项目中culster聚类函数的具体代码,由于C++语言较适用于大型程序编写,本算法又相对简单,因此未免冗长,具体完整程序见项目源程序。下面只分析Kmeans原理中(2)(3)步骤的程序实现。

    如下面程序源代码:

    bool KMeans::Cluster()
     {
        std::vector<st_pointxyz> v_center(mv_center.size());
     
        do
         {
            for (int i = 0, pntCount = mv_pntcloud.size(); i < pntCount; ++i)
             {
                double min_dist = DBL_MAX;
                 int pnt_grp = 0;
                 for (int j = 0; j < m_k; ++j)
                 {
                     double dist = DistBetweenPoints(mv_pntcloud[i].pnt, mv_center[j]);
                     if (min_dist - dist > 0.000001)
                     {
                         min_dist = dist;
                         pnt_grp = j;
                     }
                 }
                 m_grp_pntcloud[pnt_grp].push_back(st_point(mv_pntcloud[i].pnt, pnt_grp));
             }
     
             //保存上一次迭代的中心点
             for (size_t i = 0; i < mv_center.size(); ++i)
             {
                 v_center[i] = mv_center[i];
             }
     
             if (!UpdateGroupCenter(m_grp_pntcloud, mv_center))
             {
                 return false;
             }
             if (!ExistCenterShift(v_center, mv_center))
             {
                 break;
             }
             for (int i = 0; i < m_k; ++i){
                 m_grp_pntcloud[i].clear();
             }
     
         } while (true);
     
        return true;
     }

    5 算法结果分析

    原数据文件test.txt中的数据被分为三类,分别存储在文件k_1k_2k_3中,我们对三个聚类后所得数据点云进行颜色添加后显示在cloudcompare上,得下面的显示图:

    4.3 Kmeans聚类结果

    上图是在给定的初始三个聚类中心点为{ 0, 0, 0 }{ 2.5, 2.5, 2.5 }{ 3, 3, -3 }的情况下得到的结果。这是比较理想的,再看下图:

    4.4 改变初始聚类中心后的结果

    本结果对应的初始三个中心点为{ 2, 2, 2 }{ -2.5, 2.5, 2.5 }{ 3, -3, -3 },很明显,数据聚类并不理想,这说明K-Means算法一定程度上初始聚类种子点,这个聚类种子点太重要,不同的随机种子点会有得到完全不同的结果。

    上面改动了初始点,下面给出当k=4的聚类结果,分别取了两组不同的初始点集:

    4.5.1 k=4聚类结果1

    4.5.2 k=4聚类结果

    由上述聚类结果可知,当k增加时,选取聚类初始点合适,可以得到满意的结果,如5_1所示,与最初结果相比只是将球点云聚类成了两部分,而5_25_1相比结果很不理想,由颜色可以看出,图中只有两类,另外两类是空的,说明k值不当,初始值不当的情况下,聚类是会失败的。

    综上实验结果分析可以看出,kmeans聚类算法是一类非常快捷的聚类算法,效果也很明显,局部性较好,容易并行化,对大规模数据集很有意义。但比较依赖于k值得选定与初始聚类中心点的选择,所以该算法比较适合有人工参与的较大型聚类场合。

     

    工程源码:http://pan.baidu.com/s/1ntN6Pjb

    Kmeans聚类算法 - 开源中国社区 http://www.oschina.net/code/snippet_588162_50491

     

    参考文献

    [1] Hartigan J A, Wong M A. Algorithm AS 136: A k-means clustering algorithm[J]. Applied statistics, 1979: 100-108.

    展开全文
  • 关于KMeans聚类原理的动画演示,我在B站的投稿《Kmeans聚类原理 动画演示》中已作了介绍,有兴趣的朋友可以先看一下链接中的1分钟动画演示。 在[Python数据挖掘] sklearn-KMeans聚类一文中,我们调用sklearn库的...

    [问题背景]

    关于KMeans聚类原理的动画演示,我在B站的投稿《Kmeans聚类原理 动画演示》中已作了介绍,有兴趣的朋友可以先看一下链接中的1分钟动画演示。

    [Python数据挖掘] sklearn-KMeans聚类一文中,我们调用sklearn库的KMeans聚类方法,成功对以下ANSI编码的grade.txt文本文档数据集进行了聚类:

    YZN,133,108,76
    ZHY,96,145,101
    WYZ,132,107,60
    DHY,100,102,120
    CYH,139,99,93
    LHY,73,149,81
    ZHY,85,148,93
    TQP,39,138,85
    ZZL,145,112,71
    HJC,101,116,118
    XZY,99,98,117

    [问题分析]

    下面从底层实现的角度,只使用外部的random.sample和math.sqrt,无需使用numpy,逐步实现KMeans聚类算法。

    完整代码如下:

    针对grade.txt文本文档进行数据预处理并聚类的实例代码:

    (grade.txt需要与代码的.py文件位于同一目录下)

    from random import sample
    from math import sqrt
    
    # 函数名:means
    # 函数接口:大列表data
    # 函数功能:返回data大列表内所有点的平均点,是一个小列表
    def means(data):
        len_data = len(data)
        len_item = len(data[0])
        ret = []
        for j in range(len_item):
            ret_item = 0
            for i in range(len_data):
                ret_item += data[i][j]
            ret_item /= len_data
            ret.append(ret_item)
        return ret
    
    # 函数名:distance
    # 函数接口:两个数据点列表data1和data2
    # 函数功能:返回两个数据点的距离
    def distance(data1, data2):
        ret = 0
        for i in range(len(data1)):
            dif = data1[i] - data2[i]
            dif *= dif
            ret += dif
            # sqrt来自math
        ret = sqrt(ret)
        return ret
        
    # 函数名:kmeans
    # 函数接口:簇的数量n_clusters 数据列表data
    # 函数功能:返回标签labels列表
    def kmeans(n_clusters, data):
        # 簇中心列表
        centers = []
        labels = []
        len_data = len(data)
        for i in range(len_data):
            labels.append([])
    
        # 随机选择n_clusters个数据点作为初始簇中心
        # 其中sample来自random
        indexes = sample(range(0,len(data)),n_clusters)
        for i in range(n_clusters):
            centers.append(data[indexes[i]])
        len_centers = len(centers)
    
        flag = 1 # 标记簇中心是否发生变化,是为1,否为0
    
        while(flag == 1): # 如果簇中心发生变化,就继续迭代
    
            flag = 0 # 重置flag
            
            # 标签值 就是 最近簇中心标号
            # 将每个数据点与其最近的簇中心连接,将连接到同一簇中心的数据点聚为同一类(簇)
            for data_index in range(len_data):
                mindistance = float("inf") # 最近距离 初始值设置为无限大
                for center_index in range(len_centers):
                    dis = distance(data[data_index], centers[center_index])
                    if (dis < mindistance):
                        mindistance = dis
                        labels[data_index] = center_index
                    else:
                        pass
            
            # 每个簇的平均点作为新的簇中心
            for center_index in range(len_centers):
                same_label_data_list = []
                for data_index in range(len_data):
                    if (labels[data_index] == center_index):
                        same_label_data_list.append(data[data_index])
                if (centers[center_index] != means(same_label_data_list)):
                    centers[center_index] = means(same_label_data_list)
                    flag = 1
                else:
                    pass
        return labels
                
    # 数据预处理
    def loadData(filePath):
        fr = open(filePath, 'r+')
        lines = fr.readlines()
        retName = []
        retData = []
        for line in lines:
            items = line.strip().split(',')
            retName.append(items[0])
            retData.append([float(items[i]) for i in range(1,len(items))])
        return retName, retData
     
    if __name__ == '__main__':
        Name, Data = loadData('grade.txt')
        
        clusters_cnt = 3
        label = kmeans(clusters_cnt, Data)
        # print(label)
     
        outputName = []
        for i in range(clusters_cnt):
            outputName.append([])
        for i in range(len(Name)):
            outputName[label[i]].append(Name[i])
        print(outputName)
    

    运行结果为:

    [['ZHY', 'LHY', 'ZHY', 'TQP'], ['YZN', 'WYZ', 'CYH', 'ZZL'], ['DHY', 'HJC', 'XZY']]

    可以看到,这一聚类结果与我们用sklearn的KMeans得到的聚类结果是一致的。本文代码的缺点是聚类结果不够稳定(即使增加轮数使标签取众数也不稳定),但上述聚类结果占多数。如果读者知道如何像sklearn那样稳定聚类结果,还请读者不吝赐教。

    Kmeans聚类函数的实现部分:

    from random import sample
    from math import sqrt
    
    # 函数名:means
    # 函数接口:大列表data
    # 函数功能:返回data大列表内所有点的平均点,是一个小列表
    def means(data):
        len_data = len(data)
        len_item = len(data[0])
        ret = []
        for j in range(len_item):
            ret_item = 0
            for i in range(len_data):
                ret_item += data[i][j]
            ret_item /= len_data
            ret.append(ret_item)
        return ret
    
    # 函数名:distance
    # 函数接口:两个数据点列表data1和data2
    # 函数功能:返回两个数据点的距离
    def distance(data1, data2):
        ret = 0
        for i in range(len(data1)):
            dif = data1[i] - data2[i]
            dif *= dif
            ret += dif
            # sqrt来自math
        ret = sqrt(ret)
        return ret
        
    # 函数名:kmeans
    # 函数接口:簇的数量n_clusters 数据列表data
    # 函数功能:返回标签labels列表
    def kmeans(n_clusters, data):
        # 簇中心列表
        centers = []
        labels = []
        len_data = len(data)
        for i in range(len_data):
            labels.append([])
    
        # 随机选择n_clusters个数据点作为初始簇中心
        # 其中sample来自random
        indexes = sample(range(0,len(data)),n_clusters)
        for i in range(n_clusters):
            centers.append(data[indexes[i]])
        len_centers = len(centers)
    
        flag = 1 # 标记簇中心是否发生变化,是为1,否为0
    
        while(flag == 1): # 如果簇中心发生变化,就继续迭代
    
            flag = 0 # 重置flag
            
            # 标签值 就是 最近簇中心标号
            # 将每个数据点与其最近的簇中心连接,将连接到同一簇中心的数据点聚为同一类(簇)
            for data_index in range(len_data):
                mindistance = float("inf") # 最近距离 初始值设置为无限大
                for center_index in range(len_centers):
                    dis = distance(data[data_index], centers[center_index])
                    if (dis < mindistance):
                        mindistance = dis
                        labels[data_index] = center_index
                    else:
                        pass
            
            # 每个簇的平均点作为新的簇中心
            for center_index in range(len_centers):
                same_label_data_list = []
                for data_index in range(len_data):
                    if (labels[data_index] == center_index):
                        same_label_data_list.append(data[data_index])
                if (centers[center_index] != means(same_label_data_list)):
                    centers[center_index] = means(same_label_data_list)
                    flag = 1
                else:
                    pass
        return labels

     

    展开全文
  • k-means算法是非监督聚类最常用的一种方法,因其算法简单和很好的适用于大样本数据,广泛应用于不同领域,本文详细总结了k-means聚类算法原理 。目录1. k-means聚类算法原理2. k-means聚类算法步骤3. k-means++聚类...
  • KMeans聚类算法首先需要确定N个初始中心点,初始中心点的选择对聚类结果影响很大,常用的初始中心点的选择有随机选择、自定义、采用Canopy聚类算法结果作为初始中心点,然后是重复遍历点与簇中心的距离,并不断修正...
  • K-means算法是集简单和经典于一身的基于距离的聚类算法 采用距离作为相似性的评价指标,即认为两个对象的距离越近,其相似度就越大。 该算法认为类簇是由距离靠近的对象组成的,因此把得到紧凑且独立的簇作为最终...
  • 一、KMeans聚类算法原理KMeans算法的基本思想是物以类聚,人以群分。做法比较简单,初始化随机给定的 个簇中心,按照最邻近原则把样本分到各个簇中,然后计算每个簇的质心作为新的簇中心点,一直迭代,达到稳定的...
  • Kmeans聚类算法及应用

    千次阅读 2019-11-06 16:55:17
    Kmeans聚类算法原理1.2 算法图示1.3 算法要点1.3.1 核心思想1.3.2 算法步骤图解1.3.3 算法实现步骤2. Kmeans分类算法Python实战2.1 需求2.2 python代码实现2.2.1 利用numpy手动实现2.2.2 运行结果3、Kmeans算法补充...
  • 主要介绍了Python实现的KMeans聚类算法,结合实例形式较为详细的分析了KMeans聚类算法概念、原理、定义及使用相关操作技巧,需要的朋友可以参考下
  • 本文介绍了Kmeans 聚类算法原理流程以及相关核心代码
  • Kmeans聚类算法详解与实现,Kmeans算法的MATLAB实现、python实现源代码都有。附有算法原理的解析。 对应的博客地址:http://blog.csdn.net/zengxiantao1994/article/details/73441922
  • (2)掌握kmeans聚类算法原理与实现。 实验内容 1、数据见 data.mat,编程实现 K means 算法代码 K_MeansMt,并写出详细注释。 测试代码如下: load 'data.mat'; [u re]=K_MeansMt(data,3); %最后产生簇标号 re ...
  • kmeans聚类算法

    2019-11-28 14:47:27
    kmeans聚类算法的思想有如下几步 第一步 首先在数据集随机挑选k个点,分别作为这k个簇的质心 第二步 其余的点根据欧式距离公式,找到离其自身最近的质心 并合并为一类 第三步 现在我们已经初步的到聚类过的...
  • 聚类算法在实际工作中经常被使用,尤其是在数据规模较大的情况下,会先用kmeans做下聚类,分一下组。吴恩达 机器学习课程 中对kmeans讲的很清楚。K-均值是一个迭代算法,假设我们想要将数据聚类成n个组,其方法为:...
  • 前言kmeans是最简单的聚类算法之一,但是运用十分广泛。最近在工作中也经常遇到这个算法。kmeans一般在数据分析前期使用,选取适当的k,将数据分类后,然后分类研究不同聚类下数据的特点。本文记录学习kmeans算法...
  • 1. Kmeans聚类算法原理 1.1 概述 K-means算法是集简单和经典于一身的基于距离的聚类算法 采用距离作为相似性的评价指标,即认为两个对象的距离越近,其相似度就越大。 该算法认为类簇是由距离靠近的对象组成的,...
  • 主要介绍Kmeans聚类算法的数学原理,并使用matlab编程实现Kmeans的简单应用。
  • 本篇大纲:1、背景知识:一些常见的距离度量/相似度计算方式2、聚类算法Kmeans3、kmeans优缺点及其改进4、kmeans的简单代码实现上上期回顾1、我们先做了基本铺垫,对于最值求解问题进行三种类别划分,包括无约束...
  • 基于RFM模型的K均值聚类算法实现模型介绍K 均值聚类原理聚类步骤导入库读取数据正确的代码...Kmeans聚类算法利用距远近的思想将目标数据聚为指定的k个簇,进而使样本呈现簇内差异小,簇间差异大的特征。 K 均值聚类原
  • 一、KMeans聚类算法原理KMeans算法的基本思想是物以类聚,人以群分。做法比较简单,初始化随机给定的 个簇中心,按照最邻近原则把样本分到各个簇中,然后计算每个簇的质心作为新的簇中心点,一直迭代,达到稳定的...
  • 下面简要介绍Kmeans聚类原理,并附上自己写的Kmeans聚类算法实现。 一、Kmeans原理  1. 输入:一组数据data,设定需要聚类的类别数目ClusterCnt,设定迭代次数IterCnt,以及迭代截止精度eps  输出:数据data...
  • flink kmeans聚类算法实现

    千次阅读 2019-06-05 14:20:14
    kmeans聚类算法 flink版本 具体实现原理 K-Means 是迭代的聚类算法,初始设置K个聚类中心 在每一次迭代过程中,算法计算每个数据点到每个聚类中心的欧式距离 每个点被分配到它最近的聚类中心 随后每个聚类中心被...
  • 1. Kmeans聚类算法原理  1.1 概述  K-means算法是集简单和经典于一身的基于距离的聚类算法  采用距离作为相似性的评价指标,即认为两个对象的距离越近,其相似度就越大。  该算法认为类簇是由距离靠近的对象组成...
  • Kmeans 聚类算法

    2021-02-20 12:36:24
    KMeans算法属于无监督学习,解决聚类的问题 对于数据集D, 不需提供数据标记,大大减少工作量 数据集D必须是凸集,非凸数据集难以收敛 必须先指定聚类簇数k k-means优点 原理简单,实现容易,可解释性较强 聚类...
  • Spark自编程实现Kmeans聚类算法

    千次阅读 2018-11-28 23:33:08
    Spark实现 – Kmeans聚类算法 Kmeans简介 Kmeans是最常用的聚类算法,也是十大经典的数据挖掘算法之一。聚类的思想用一句话概括就是“物以类聚,人以群分”。kmeans算法作为最基础的算法之一,基本上每本数据挖掘的...
  • 随机生成质心由于这是一个无监督学习的算法,因此我们首先在一个二维的坐标轴下随机给定一堆点,并随即给定两个质心,我们这个算法的目的就是将这一堆点根据它们自身的坐标特征分为两类,因此选取了两个质心,什么...
  • Kmeans是我接触的第一个机器学习算法原理简单,却很实用,只要一想到聚类,基本上没有Kmeans解决不了的问题(此处略有夸张~~),本篇整理了Kmeans聚类原理,评判标准以及Sklearn实现过程 一、Kmeans聚类原理 用...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 455
精华内容 182
关键字:

kmeans聚类算法原理