精华内容
下载资源
问答
  • 大家好呀,我是AI菌,今天和大家分享机器学习里面的简单入门分类算法KMeans、KNN、Meanshift,话不多说我们进入正题! KMeans k均值聚类算法(k-means clustering algorithm)是一种迭代求解的聚类分析算法,其...

    大家好呀,我是AI菌,今天和大家分享机器学习里面的简单入门分类算法:KMeans、KNN、Meanshift,话不多说我们进入正题!

    KMeans

    k均值聚类算法(k-means clustering algorithm)是一种迭代求解的聚类分析算法,其步骤是,预将数据分为K组,则随机选取K个对象作为初始的聚类中心,然后计算每个对象与各个种子聚类中心之间的距离,把每个对象分配给距离它最近的聚类中心。聚类中心以及分配给它们的对象就代表一个聚类。每分配一个样本,聚类的聚类中心会根据聚类中现有的对象被重新计算。这个过程将不断重复直到满足某个终止条件。终止条件可以是没有(或最小数目)对象被重新分配给不同的聚类,没有(或最小数目)聚类中心再发生变化,误差平方和局部最小。

    KMeans的介绍大家可能看的一知半解,我们用实战运用一下:
    我们引入一个已经标注好的样本,并且可视化

    import pandas as pd
    import numpy as np
    data = pd.read_csv('data.csv')
    X = data.drop(['labels'],axis=1)
    y = data.loc[:,'labels']
    fig1 = plt.figure()
    label0 = plt.scatter(X.loc[:,'V1'][y==0],X.loc[:,'V2'][y==0])
    label1 = plt.scatter(X.loc[:,'V1'][y==1],X.loc[:,'V2'][y==1])
    label2 = plt.scatter(X.loc[:,'V1'][y==2],X.loc[:,'V2'][y==2])
    plt.title("labled data")
    plt.xlabel('V1')
    plt.ylabel('V2')
    plt.legend((label0,label1,label2),('label0','label1','label2'))
    plt.show()
    

    在这里插入图片描述
    运用KMeans模型

    from sklearn.cluster import KMeans
    KM = KMeans(n_clusters3,random_state=0 #c_clusters为分成若干类,random可理解成每个类随机标签
    KM.fit(X)#模型训练
    center = KM.cluster_center_#显示训练后的中心点
    print(center)
    

    结果:array([[ 40.68362784, 59.71589274],[ 69.92418447, -10.11964119], [ 9.4780459 , 10.686052 ]])
    我们把中心点在上图可视化,如下:
    在这里插入图片描述
    模型训练完成后,要进行模型的预测以及预测结果可视化:

    y_predict = KM.predict(X)
    #visualize the data and results
    fig4 = plt.subplot(121)
    label0 = plt.scatter(X.loc[:,'V1'][y_predict==0],X.loc[:,'V2'][y_predict==0])
    label1 = plt.scatter(X.loc[:,'V1'][y_predict==1],X.loc[:,'V2'][y_predict==1])
    label2 = plt.scatter(X.loc[:,'V1'][y_predict==2],X.loc[:,'V2'][y_predict==2])
    
    plt.title("predicted data")
    plt.xlabel('V1')
    plt.ylabel('V2')
    plt.legend((label0,label1,label2),('label0','label1','label2'))
    plt.scatter(centers[:,0],centers[:,1])
    

    在这里插入图片描述
    对比发现,预测结果和实际结果大致相同,但因为是无监督学习,每个类的标签不一样,所以和实际结果的标签有误,最后进行结果矫正:

    y_corrected = []
    for i in y_predict:
        if i==0:
            y_corrected.append(2)
        elif i==2:
            y_corrected.append(0)
        else:
            y_corrected.append(1)
    

    最后用y_corrected为标签进行可视化,就完成矫正啦~~而且准确率为0.997
    在这里插入图片描述

    Meanshift

    Mean Shift算法的关键操作是通过感兴趣区域内的数据密度变化计算中心点的漂移向量,从而移动中心点进行下一次迭代,直到到达密度最大处(中心点不变)。从每个数据点出发都可以进行该操作,在这个过程,统计出现在感兴趣区域内的数据的次数。该参数将在最后作为分类的依据。
    与K-Means算法不一样的是,Mean Shift算法可以自动决定类别的数目。与K-Means算法一样的是,两者都用集合内数据点的均值进行中心点的移动。
    下图为MeanShitf的流程图:
    在这里插入图片描述
    实战环节:

    from sklearn.cluster import MeanShift,estimate_bandwidth
    bw = estimate_bandwidth(X,n_samples=500)#X为原始数据集,n_samples为取若干的点进行估计带宽(半径)
    #estimate_bandwidth函数用作于mean-shift算法估计带宽,如果MeanShift函数没有传入bandwidth参数,MeanShift会自动运行estimate_bandwidth
    ms = MeanShift(bandwidth=bw)
    ms.fit(X)
    y_predict_ms = ms.predict(X)
    #最后直接进行可视化
    fig6 = plt.subplot(121)
    label0 = plt.scatter(X.loc[:,'V1'][y_predict_ms==0],X.loc[:,'V2'][y_predict_ms==0])
    label1 = plt.scatter(X.loc[:,'V1'][y_predict_ms==1],X.loc[:,'V2'][y_predict_ms==1])
    label2 = plt.scatter(X.loc[:,'V1'][y_predict_ms==2],X.loc[:,'V2'][y_predict_ms==2])
    
    plt.title("ms results")
    plt.xlabel('V1')
    plt.ylabel('V2')
    plt.legend((label0,label1,label2),('label0','label1','label2'))
    plt.scatter(centers[:,0],centers[:,1])
    plt.show()
    

    在这里插入图片描述
    因为MeanShift为非监督学习,所以最后标签有可能和原始标签不合,我们要进行结果矫正,方法和KMeans基本相同,就不展示啦~~

    knn的话,下期手撸knn源码和大家分享!!

    拓展

    K-means算法是将样本聚类成k个簇(cluster),具体算法描述如下:
    1、 随机选取k个聚类质心点(cluster centroids)为在这里插入图片描述
    2、 重复下面过程直到收敛 :
    对于每一个样例i,计算其应该属于的类
    在这里插入图片描述
    对于每一个类j,重新计算该类的质心
    在这里插入图片描述
    K是我们事先给定的聚类数,Ci代表样例i与k个类中距离最近的那个类,Ci的值是1到k中的一个。质心μi代表我们对属于同一个类的样本中心点的猜测.

    展开全文
  • MATLAB实现的Kmeans算法,根据输入的初始中心和数据进行分类
  • 截至目前为止,还没有深入的刨析kmeans算法的工作原理(会用和知道怎么用,跟理解背后深刻的数学原理是本质区别的,我对此深感敬畏)。今天站在工程应用的角度,刨析kmeans在应用过程的应用和优化。主要是弥补我上篇...

    ***题记:*我一直在路上,害怕停下
    在这里插入图片描述
    在我的另一篇博客里《读sklearn源码学机器学习——kmeans聚类算法》我详细的阐述了kmeans算法的工作过程。截至目前为止,还没有深入的刨析kmeans算法的工作原理(会用和知道怎么用,跟理解背后深刻的数学原理是有本质区别的,我对此深感敬畏)。其实kmeas算法和高斯混合算法都是em算法的具体应用。今天站在工程应用的角度,刨析kmeans在工程中的应用和优化。主要是弥补我上篇博客中没有说明白的两个函数(elativeDist,squaredNorna)和一个初始化。

    1、kmeans++算法

    kmeans++是David Arthur and Sergei Vassilvitskii在一篇名为“k-means++: The Advantages of Careful Seeding(http://ilpubs.stanford.edu:8090/778/1/2006-13.pdf)文中中首次提及的,可以用来解决kmeans在初始化的时候,随机选取初始点带来的负面影响。算法的工作过程如下:
    在这里插入图片描述
    翻译成中文:
    1a、随机的选取一个样本点作为一个一个聚类中心。
    2b、在选择下一个聚类中心的时候,以到达现有聚类中心的距离为依据进行聚类中心得选择。离现在的聚类中心越远被选择的概率越大。
    (一般通过轮盘赌选择,概率一般用欧式距离平方占比)
    1c、重复上述的过程直到选出所有的聚类中心。
    基本依据:在选择初始距离的时候,样本之间离得越远越好。
    kmeans++实现过程:
    数据通过矩阵的形式存在matrix_data中(个人觉得自己的实现过程还是优雅且美妙的)。
    (可以仔细体会下对轮盘赌的实现过程以及numpy相应函数的应用,可以猜测np.searchsorted()的算法复杂度最高时log(n),比我们遍历选取要划算多了)

    center=np.zeros((n_cluster,n_feature))
    center[0]=matrix_data[np.random.randint(n_samples)]
    for i in range(1,n_cluster):
        #计算每个样本点到已有中心点的距离
        distance_to_centers=euclideanDistance(matrix_data,center[[i for i in range(i)]],square=True)
        #选取据距离最小值
        closed_distance=np.min(distance_to_centers,axis=1)
        #轮盘赌
        denominator=closed_distance.sum()
        point=np.random.rand()*denominator#轮盘赌的指针
        be_choosed=np.searchsorted(np.cumsum(closed_distance),point)
        be_choosed=min(be_choosed,n_samples-1)#避免选的是最后一个而造成下标越界
        center[i]=matrix_data[be_choosed]
    

    其中欧式距离的计算函数euclideanDistance实现原理在上一篇博客中证明过,过程如下:

    import pandas as pd
    import numpy as np
    def rowNorms(X):#对行每个元素取平方加和
        return np.einsum("ij,ij->i",X,X)
    def euclideanDistance(x,y,square=False):#x的每个样本与y之间的距离
        """
        :param x: 矩阵x
        :param y: 矩阵y
        :param squared: 表示是否返回二者欧式距离的平方值,很明显如果返回欧式距离的平方,计算量又小一些
        :return: 矩阵x中的每一个样本与y中样本之间的距离
        """
        """
        对于这个操作的理解一定要理解下面这个操作
        np.array([[1],[2],[1]])+np.array([[1,2,3],[4,5,6],[7,8,9]])
        Out[28]:
                array([[ 2,  3,  4],
                       [ 6,  7,  8],
                       [ 8,  9, 10]])
        np.array([[ 2,  3,  4],[ 6,  7,  8],[ 8,  9, 10]])+np.array([1,2,3])
        Out[28]:
                array([[ 3,  5,  7],
                       [ 7,  9, 11],
                       [ 9, 11, 13]])
        P矩阵与C矩阵每一行之间的距离可以用公式[[p1^2],[p2^2],[...]]-2PC^T+[c1^2,c2^2,c3^2...]
        (p1^2是p1行向量平方和,c1^2是c1行向量平方和)
        """
        xx=rowNorms(x)[:,np.newaxis]#转化为列向量,便于让dot的每一行都相加同一个数
        yy=rowNorms(y)[np.newaxis,:]#与xx同理
        dot=np.dot(x,y.T)
        res = xx + yy - 2 * dot
        return res if square else np.sqrt(res)
    

    kmeans++的优化

    该方法David Arthur and Sergei Vassilvitskii没有发表出来,但是在机器学习开源社区上被用到,即在用kmeas++计算距离的过程中,每一轮再增加一个最大迭代次数,比如通过轮盘赌一次选取n_local_trials个,然后再依次选取能做到使距离平方和最小的聚类中心点(总距离平方和最小中的离现有中心点最大的点)。n_local_trals的选取原则为(2+log(聚类中心点数))。
    实现过程如下(引用的sklearn开源社区源码(https://github.com/scikit-learn/scikit-learn)):

    n_samples, n_features = X.shape
    centers = np.empty((n_clusters, n_features), dtype=X.dtype)
    n_local_trials = 2 + int(np.log(n_clusters))
    center_id = random_state.randint(n_samples)
    centers[0] = X[center_id]
    closest_dist_sq = euclidean_distances(
        centers[0, np.newaxis], X, Y_norm_squared=x_squared_norms,
        squared=True)
    current_pot = closest_dist_sq.sum()
    for c in range(1, n_clusters):
        rand_vals = random_state.random_sample(n_local_trials) * current_pot
        candidate_ids = np.searchsorted(stable_cumsum(closest_dist_sq),
                                        rand_vals)
        np.clip(candidate_ids, None, closest_dist_sq.size - 1,
                out=candidate_ids)
    
        distance_to_candidates = euclidean_distances(
            X[candidate_ids], X, Y_norm_squared=x_squared_norms, squared=True)
        np.minimum(closest_dist_sq, distance_to_candidates,
                   out=distance_to_candidates)
        candidates_pot = distance_to_candidates.sum(axis=1)
        best_candidate = np.argmin(candidates_pot)
        current_pot = candidates_pot[best_candidate]
        closest_dist_sq = distance_to_candidates[best_candidate]
        best_candidate = candidate_ids[best_candidate]
        centers[c] = X[best_candidate]
    
    return centers
    
    

    距离计算的优化

    假设有4个样本3个特征如下:

    _f1f2f3
    1123
    2456
    3789
    4101112

    再比如想要把样本聚类为2类,这样类的聚类中线为1和2。将上面数据存为矩阵:
    x=np.array([[1,2,3],[4,5,6],[7,8,9],[10,11,12]])
    通过euclideanDistance计算所有样本点到两个聚类中心的距离,如下:

    euclideanDistance(x,x[[0,1]])
    Out[4]: 
    array([[ 0.        ,  5.19615242],
           [ 5.19615242,  0.        ],
           [10.39230485,  5.19615242],
           [15.58845727, 10.39230485]])
    

    结果显示1到样本1的距离0,到样本2的距离为5.19615242,2到样本1的距离为5.19615242到样本2的距离为0,依次类推我们就得到了各个样本到各个聚类中心的距离,并以此将各个样本贴上不同的类别标签上面的类别标签为[1,2,2,2]。
    所以我们再选择的过程中直接比较的是行向量的相对大小,那如果我们在求||x-x[[0,1]]||的时候行向量同时减去一个||x||^2哪?分类的结果其实是不变的,但是对于这里的距离求取过程却可以简化为如下:

    def relativeDist(x,y):#x的每个样本与y之间的相对距离
        """
        我们知道,如果单纯选出x行向量与y之间最小的距离,完全可以同时减去xx
        也就是(x-y)^2-x^2
        """
        yy=rowNorms(y)[np.newaxis,:]
        dot=np.dot(x,y.T)
        res=-2*dot+yy
        return res
    

    该方法在计算距离的时候每次减少的计算量与x的大小成正比,减少了计算量。
    上面例子用relativeDist求取的结果为:

    relativeDist(x,x[[0,1]])
    Out[5]: 
    array([[ -14,   13],
           [ -50,  -77],
           [ -86, -167],
           [-122, -257]])
    

    分类结果依然是[1,2,2,2]。

    展开全文
  • 1. 写在前面如果想从事数据挖掘或者机器学习的工作,掌握常用的机器学习算法是非常必要的,常见的机器学习算法:监督学习算法:逻辑回归,线性回归,决策树,朴素贝叶斯,K近邻,支持向量机,集成算法Adaboost等无...

    1. 写在前面

    如果想从事数据挖掘或者机器学习的工作,掌握常用的机器学习算法是非常有必要的,常见的机器学习算法:

    • 监督学习算法:逻辑回归,线性回归,决策树,朴素贝叶斯,K近邻,支持向量机,集成算法Adaboost等
    • 无监督算法:聚类,降维,关联规则, PageRank等

    为了详细的理解这些原理,曾经看过西瓜书,统计学习方法,机器学习实战等书,也听过一些机器学习的课程,但总感觉话语里比较深奥,读起来没有耐心,并且理论到处有,而实战最重要, 所以在这里想用最浅显易懂的语言写一个白话机器学习算法理论+实战系列

    个人认为,理解算法背后的idea和使用,要比看懂它的数学推导更加重要。idea会让你有一个直观的感受,从而明白算法的合理性,数学推导只是将这种合理性用更加严谨的语言表达出来而已,打个比方,一个梨很甜,用数学的语言可以表述为糖分含量90%,但只有亲自咬一口,你才能真正感觉到这个梨有多甜,也才能真正理解数学上的90%的糖分究竟是怎么样的。如果算法是个梨,本文的首要目的就是先带领大家咬一口。另外还有下面几个目的:

    • 检验自己对算法的理解程度,对算法理论做一个小总结
    • 能开心的学习这些算法的核心思想, 找到学习这些算法的兴趣,为深入的学习这些算法打一个基础。
    • 每一节课的理论都会放一个实战案例,能够真正的做到学以致用,既可以锻炼编程能力,又可以加深算法理论的把握程度。
    • 也想把之前所有的笔记和参考放在一块,方便以后查看时的方便。

    学习算法的过程,获得的不应该只有算法理论,还应该有乐趣和解决实际问题的能力!

    今天是白话机器学习算法理论+实战的第八篇 之KMeans聚类算法, 听到这个名字,你可别和第七篇K近邻算法搞混了,K-Means 是一种非监督学习,解决的是聚类问题,这里的K表示的是聚成K类。而之前的K近邻算法是监督学习算法,解决的是分类问题,这里的K表示的是K个邻居。相差十万八千里吧, 一条取经路呢。一定要区分开。这个算法也不是很难,前面说道,K近邻算法的原理可以用八个大字叫做“近朱者赤,近墨者黑”来总结,这里我依然放出八个大字:“人以类聚,物以群分”,形容KMeans最好不过了。

    通过今天的学习,掌握KMeans算法的工作原理,然后会使用sklearn实现KMeans聚类,最后我们来做一个实战项目:如何使用KMeans对图像进行分割? 下面我们开始吧。

    大纲如下:

    • KMeans聚类的工作原理(结合足球队等级划分谈一谈)
    • 20支亚洲足球队,你能划分出等级吗?(KMeans聚类应用)
    • KMeans聚类的实战:图像分割

    OK, let's go!

    2. K-Means的工作原理

    上面我们说过,K-Means 是一种非监督学习,解决的是聚类问题。K 代表的是 K 类,Means 代表的是中心,你可以理解这个算法的本质是确定 K 类的中心点,当你找到了这些中心点,也就完成了聚类。

    那么这里有两个问题:如何确定K类的中心点?如何把其他类划分到K个类中去?

    先别慌, 先和我考虑一个场景,假设我有 20 支亚洲足球队,想要将它们按照成绩划分成 3 个等级,可以怎样划分?

    元芳, 你怎么看?

    对亚洲足球队的水平,你可能也有自己的判断。比如一流的亚洲球队有谁?你可能会说伊朗或韩国。二流的亚洲球队呢?你可能说是中国。三流的亚洲球队呢?你可能会说越南。

    其实这些都是靠我们的经验来划分的,那么伊朗、中国、越南可以说是三个等级的典型代表,也就是我们每个类的中心点。

    所以回过头来,如何确定 K 类的中心点?一开始我们是可以随机指派的,当你确认了中心点后,就可以按照距离将其他足球队划分到不同的类别中。

    这也就是 K-Means 的中心思想,就是这么简单直接。

    你可能会问:如果一开始,选择一流球队是中国,二流球队是伊朗,三流球队是韩国,中心点选择错了怎么办?其实不用担心,K-Means 有自我纠正机制,在不断的迭代过程中,会纠正中心点。中心点在整个迭代过程中,并不是唯一的,只是你需要一个初始值,一般算法会随机设置初始的中心点。

    那下面就给出K-Means的工作原理,两步就搞定,就是那两个问题的解决:

    1. 选取 K 个点作为初始的类中心点,这些点一般都是从数据集中随机抽取的;
    2. 将每个点分配到最近的类中心点,这样就形成了 K 个类,然后重新计算每个类的中心点;(这个怎么算最近,一般是欧几里得距离公式, 那么怎么重新计算每个类的中心点, 每个维度的平均值就可以的)
    3. 重复第二步,直到类不发生变化,或者你也可以设置最大迭代次数,这样即使类中心点发生变化,但是只要达到最大迭代次数就会结束。

    什么?还不明白? 好吧,那直接看看亚洲球队聚类的例子吧

    3. 如何给亚洲球队做聚类

    对于机器来说需要数据才能判断类中心点,所以下面整理了 2015-2019 年亚洲球队的排名,如下表所示。

    我来说明一下数据概况。

    其中 2019 年国际足联的世界排名,2015 年亚洲杯排名均为实际排名。2018 年世界杯中,很多球队没有进入到决赛圈,所以只有进入到决赛圈的球队才有实际的排名。如果是亚洲区预选赛 12 强的球队,排名会设置为 40。如果没有进入亚洲区预选赛 12 强,球队排名会设置为 50。d467e4ae1f10104b893ec267311ede7a.png我们怎么做聚类呢?可以跟着我的思路走了:

    • 首先,针对上面的排名,我们需要做的就是数据规范化,你可以把这些值划分到[0,1]或者按照均值为 0,方差为 1 的正态分布进行规范化。我先把数值规范化到了[0,1]空间中,得到了下面的数值表:bbef88065ca22862cbec1bbad6782f5a.png如果我们随机选取中国、日本、韩国为三个类的中心点,我们就需要看下这些球队到中心点的距离。

    • 下面就是把其其他样本根据距离中心点的远近划分到这三个类中去,有关距离可以参考KNN那一篇博客。 常用的有欧氏距离,曼哈顿距离等。这里采用欧式距离。

    欧氏距离是最常用的距离计算方式,这里选择欧氏距离作为距离的标准,计算每个队伍分别到中国、日本、韩国的距离,然后根据距离远近来划分。我们看到大部分的队,会和中国队聚类到一起。这里我整理了距离的计算过程,比如中国和中国的欧氏距离为 0,中国和日本的欧式距离为 0.732003。如果按照中国、日本、韩国为 3 个分类的中心点,欧氏距离的计算结果如下表所示:94dda8c29d435432e74d30d7f5323319.png然后我们再重新计算这三个类的中心点,如何计算呢?最简单的方式就是取平均值,然后根据新的中心点按照距离远近重新分配球队的分类,再根据球队的分类更新中心点的位置。计算过程这里不展开,最后一直迭代(重复上述的计算过程:计算中心点和划分分类)到分类不再发生变化,可以得到以下的分类结果:5e4d683cc62eece24e292f838bd20179.png所以我们能看出来第一梯队有日本、韩国、伊朗、沙特、澳洲;第二梯队有中国、伊拉克、阿联酋、乌兹别克斯坦;第三梯队有卡塔尔、泰国、越南、阿曼、巴林、朝鲜、印尼、叙利亚、约旦、科威特和巴勒斯坦。

    这个就是KMeans进行聚类的过程了。简单点,就是反复两个过程:

    • 确定中心点
    • 把其他的点按照距中心点的远近归到相应的中心点

    上面这个也可以使用sklearn中的K-Means进行实战一下子,作为图像分割图像的准备期。

    4. KMeans聚类实战:如何使用KMeans对图像进行分割?

    还是老规矩,我们在实战之前,先看一下如何调用sklearn实现KMeans。

    4.1 如何使用sklearn中的KMeans算法

    sklearn 是 Python 的机器学习工具库,如果从功能上来划分,sklearn 可以实现分类、聚类、回归、降维、模型选择和预处理等功能。这里我们使用的是 sklearn 的聚类函数库,因此需要引用工具包,具体代码如下:

    from sklearn.cluster import KMeans

    当然 K-Means 只是 sklearn.cluster 中的一个聚类库,实际上包括 K-Means 在内,sklearn.cluster 一共提供了 9 种聚类方法,比如 Mean-shift,DBSCAN,Spectral clustering(谱聚类)等。这些聚类方法的原理和 K-Means 不同,这里不做介绍。

    我们看下 K-Means 如何创建:

    KMeans(n_clusters=8, init='k-means++', n_init=10, max_iter=300, tol=0.0001, precompute_distances='auto', verbose=0, random_state=None, copy_x=True, n_jobs=1, algorithm='auto')

    这些参数解释一下:

    • n_clusters: 即 K 值,一般需要多试一些 K 值来保证更好的聚类效果。你可以随机设置一些 K 值,然后选择聚类效果最好的作为最终的 K 值;max_iter:最大迭代次数,如果聚类很难收敛的话,设置最大迭代次数可以让我们及时得到反馈结果,否则程序运行时间会非常长;
    • n_init:初始化中心点的运算次数,默认是 10。程序是否能快速收敛和中心点的选择关系非常大,所以在中心点选择上多花一些时间,来争取整体时间上的快速收敛还是非常值得的。由于每一次中心点都是随机生成的,这样得到的结果就有好有坏,非常不确定,所以要运行 n_init 次, 取其中最好的作为初始的中心点。如果 K 值比较大的时候,你可以适当增大 n_init 这个值;
    • init:即初始值选择的方式,默认是采用优化过的 k-means++ 方式,你也可以自己指定中心点,或者采用 random 完全随机的方式。自己设置中心点一般是对于个性化的数据进行设置,很少采用。random 的方式则是完全随机的方式,一般推荐采用优化过的 k-means++ 方式;
    • algorithm:k-means 的实现算法,有“auto” “full”“elkan”三种。一般来说建议直接用默认的"auto"。简单说下这三个取值的区别,如果你选择"full"采用的是传统的 K-Means 算法,“auto”会根据数据的特点自动选择是选择“full”还是“elkan”。我们一般选择默认的取值,即“auto” 。

    在创建好 K-Means 类之后,就可以使用它的方法,最常用的是 fit 和 predict 这个两个函数。你可以单独使用 fit 函数和 predict 函数,也可以合并使用 fit_predict 函数。其中 fit(data) 可以对 data 数据进行 k-Means 聚类。predict(data) 可以针对 data 中的每个样本,计算最近的类。

    下面我们先跑一遍20支亚洲球队的聚类问题:数据集在这下载


    # coding: utf-8
    from sklearn.cluster import KMeans
    from sklearn import preprocessing
    import pandas as pd
    import numpy as np
    # 输入数据
    data = pd.read_csv('data.csv', encoding='gbk')
    train_x = data[["2019年国际排名","2018世界杯","2015亚洲杯"]]
    df = pd.DataFrame(train_x)
    kmeans = KMeans(n_clusters=3)
    # 规范化到[0,1]空间
    min_max_scaler=preprocessing.MinMaxScaler()
    train_x=min_max_scaler.fit_transform(train_x)
    # kmeans算法
    kmeans.fit(train_x)
    predict_y = kmeans.predict(train_x)
    # 合并聚类结果,插入到原数据中
    result = pd.concat((data,pd.DataFrame(predict_y)),axis=1)
    result.rename({0:u'聚类'},axis=1,inplace=True)
    print(result)

    运行结果如下:


    国家 2019年国际排名 2018世界杯 2015亚洲杯 聚类
    0 中国 73 40 7 2
    1 日本 60 15 5 0
    2 韩国 61 19 2 0
    3 伊朗 34 18 6 0
    4 沙特 67 26 10 0
    5 伊拉克 91 40 4 2
    6 卡塔尔 101 40 13 1
    7 阿联酋 81 40 6 2
    8 乌兹别克斯坦 88 40 8 2
    9 泰国 122 40 17 1
    10 越南 102 50 17 1
    11 阿曼 87 50 12 1
    12 巴林 116 50 11 1
    13 朝鲜 110 50 14 1
    14 印尼 164 50 17 1
    15 澳洲 40 30 1 0
    16 叙利亚 76 40 17 1
    17 约旦 118 50 9 1
    18 科威特 160 50 15 1
    19 巴勒斯坦 96 50 16 1

    4.2 如何用KMeans对图像进行分割?

    图像分割就是利用图像自身的信息,比如颜色、纹理、形状等特征进行划分,将图像分割成不同的区域,划分出来的每个区域就相当于是对图像中的像素进行了聚类。单个区域内的像素之间的相似度大,不同区域间的像素差异性大。这个特性正好符合聚类的特性,所以你可以把图像分割看成是将图像中的信息进行聚类。当然聚类只是分割图像的一种方式,除了聚类,我们还可以基于图像颜色的阈值进行分割,或者基于图像边缘的信息进行分割等。

    将微信开屏封面进行分割。

    我们现在用 K-Means 算法对微信页面进行分割。微信开屏图如下所示:b6c780b7fc59a7262ba6720215ad7827.png我们先设定下聚类的流程,聚类的流程和分类差不多,如图所示:17c74c71f7d143ab713f37631bc1f414.png在准备阶段里,我们需要对数据进行加载。因为处理的是图像信息,我们除了要获取图像数据以外,还需要获取图像的尺寸和通道数,然后基于图像中每个通道的数值进行数据规范化。这里我们需要定义个函数 load_data,来帮我们进行图像加载和数据规范化。代码如下:

    # 加载图像,并对数据进行规范化
    def load_data(filePath):
    # 读文件
    f = open(filePath,'rb')
    data = []
    # 得到图像的像素值
    img = image.open(f)
    # 得到图像尺寸
    width, height = img.size
    for x in range(width):
    for y in range(height):
    # 得到点(x,y)的三个通道值
    c1, c2, c3 = img.getpixel((x, y))
    data.append([c1, c2, c3])
    f.close()
    # 采用Min-Max规范化
    mm = preprocessing.MinMaxScaler()
    data = mm.fit_transform(data)
    return np.mat(data), width, height

    因为 jpg 格式的图像是三个通道 (R,G,B),也就是一个像素点具有 3 个特征值。这里我们用 c1、c2、c3 来获取平面坐标点 (x,y) 的三个特征值,特征值是在 0-255 之间。

    为了加快聚类的收敛,我们需要采用 Min-Max 规范化对数据进行规范化。我们定义的 load_data 函数返回的结果包括了针对 (R,G,B) 三个通道规范化的数据,以及图像的尺寸信息。在定义好 load_data 函数后,我们直接调用就可以得到相关信息,代码如下:

    # 加载图像,得到规范化的结果img,以及图像尺寸
    img, width, height = load_data('./weixin.jpg')

    假设我们想要对图像分割成 2 部分,在聚类阶段,我们可以将聚类数设置为 2,这样图像就自动聚成 2 类。代码如下:

    # 用K-Means对图像进行2聚类
    kmeans =KMeans(n_clusters=2)
    kmeans.fit(img)
    label = kmeans.predict(img)
    # 将图像聚类结果,转化成图像尺寸的矩阵
    label = label.reshape([width, height])
    # 创建个新图像pic_mark,用来保存图像聚类的结果,并设置不同的灰度值
    pic_mark = image.new("L", (width, height))
    for x in range(width):
    for y in range(height):
    # 根据类别设置图像灰度, 类别0 灰度值为255, 类别1 灰度值为127
    pic_mark.putpixel((x, y), int(256/(label[x][y]+1))-1)
    pic_mark.save("weixin_mark.jpg", "JPEG")

    代码中有一些参数,下面说一下这些参数的作用和设置方法:

    我们使用了 fit 和 predict 这两个函数来做数据的训练拟合和预测,因为传入的参数是一样的,我们可以同时进行 fit 和 predict 操作,这样我们可以直接使用 fit_predict(data) 得到聚类的结果。得到聚类的结果 label 后,实际上是一个一维的向量,我们需要把它转化成图像尺寸的矩阵。label 的聚类结果是从 0 开始统计的,当聚类数为 2 的时候,聚类的标识 label=0 或者 1。
    如果你想对图像聚类的结果进行可视化,直接看 0 和 1 是看不出来的,还需要将 0 和 1 转化为灰度值。灰度值一般是在 0-255 的范围内,我们可以将 label=0 设定为灰度值 255,label=1 设定为灰度值 127。具体方法是用 int(256/(label[x][y]+1))-1。可视化的时候,主要是通过设置图像的灰度值进行显示。所以我们把聚类 label=0 的像素点都统一设置灰度值为 255,把聚类 label=1 的像素点都统一设置灰度值为 127。原来图像的灰度值是在 0-255 之间,现在就只有 2 种颜色(也就是灰度为 255,和灰度 127)。

    有了这些灰度信息,我们就可以用 image.new 创建一个新的图像,用 putpixel 函数对新图像的点进行灰度值的设置,最后用 save 函数保存聚类的灰度图像。这样你就可以看到聚类的可视化结果了,如下图所示:47590d7f2b7fb02b67d8c3d5a8b750fe.png如果我们想要分割成 16 个部分,该如何对不同分类设置不同的颜色值呢?这里需要用到 skimage 工具包,它是图像处理工具包。你需要使用 pip install scikit-image 来进行安装。这段代码可以将聚类标识矩阵转化为不同颜色的矩阵:

    from skimage import color
    # 将聚类标识矩阵转化为不同颜色的矩阵
    label_color = (color.label2rgb(label)*255).astype(np.uint8)
    label_color = label_color.transpose(1,0,2)
    images = image.fromarray(label_color)
    images.save('weixin_mark_color.jpg')

    代码中,我使用 skimage 中的 label2rgb 函数来将 label 分类标识转化为颜色数值,因为我们的颜色值范围是[0,255],所以还需要乘以 255 进行转化,最后再转化为 np.uint8 类型。unit8 类型代表无符号整数,范围是 0-255 之间。

    得到颜色矩阵后,你可以把它输出出来,这时你发现输出的图像是颠倒的,原因可能是图像源拍摄的时候本身是倒置的。我们需要设置三维矩阵的转置,让第一维和第二维颠倒过来,也就是使用 transpose(1,0,2),将原来的 (0,1,2)顺序转化为 (1,0,2) 顺序,即第一维和第二维互换。

    最后我们使用 fromarray 函数,它可以通过矩阵来生成图片,并使用 save 进行保存。最后得到的分类标识颜色化图像是这样的:ebd73041e09db2c9d90cb83c97b10524.png刚才我们做的是聚类的可视化。如果我们想要看到对应的原图,可以将每个簇(即每个类别)的点的 RGB 值设置为该簇质心点的 RGB 值,也就是簇内的点的特征均为质心点的特征。

    我给出了完整的代码,代码中,我可以把范围为 0-255 的数值投射到 1-256 数值之间,方法是对每个数值进行加 1,你可以自己来运行下:

    # -*- coding: utf-8 -*-
    # 使用K-means对图像进行聚类,并显示聚类压缩后的图像
    import numpy as np
    import PIL.Image as image
    from sklearn.cluster import KMeans
    from sklearn import preprocessing
    import matplotlib.image as mpimg
    # 加载图像,并对数据进行规范化
    def load_data(filePath):
    # 读文件
    f = open(filePath,'rb')
    data = []
    # 得到图像的像素值
    img = image.open(f)
    # 得到图像尺寸
    width, height = img.size
    for x in range(width):
    for y in range(height):
    # 得到点(x,y)的三个通道值
    c1, c2, c3 = img.getpixel((x, y))
    data.append([(c1+1)/256.0, (c2+1)/256.0, (c3+1)/256.0])
    f.close()
    return np.mat(data), width, height
    # 加载图像,得到规范化的结果imgData,以及图像尺寸
    img, width, height = load_data('./weixin.jpg')
    # 用K-Means对图像进行16聚类
    kmeans =KMeans(n_clusters=16)
    label = kmeans.fit_predict(img)
    # 将图像聚类结果,转化成图像尺寸的矩阵
    label = label.reshape([width, height])
    # 创建个新图像img,用来保存图像聚类压缩后的结果
    img=image.new('RGB', (width, height))
    for x in range(width):
    for y in range(height):
    c1 = kmeans.cluster_centers_[label[x, y], 0]
    c2 = kmeans.cluster_centers_[label[x, y], 1]
    c3 = kmeans.cluster_centers_[label[x, y], 2]
    img.putpixel((x, y), (int(c1*256)-1, int(c2*256)-1, int(c3*256)-1))
    img.save('weixin_new.jpg')

    结果如下:51172397bfabd8bff9d4600762f83c9d.png你可以看到我没有用到 sklearn 自带的 MinMaxScaler,而是自己写了 Min-Max 规范化的公式。这样做的原因是我们知道 RGB 每个通道的数值在[0,255]之间,所以我们可以用每个通道的数值 +1/256,这样数值就会在[0,1]之间。

    对图像做了 Min-Max 空间变换之后,还可以对其进行反变换,还原出对应原图的通道值。对于点 (x,y),我们找到它们所属的簇 label[x,y],然后得到这个簇的质心特征,用 c1,c2,c3 表示:

    c1 = kmeans.cluster_centers_[label[x, y], 0]
    c2 = kmeans.cluster_centers_[label[x, y], 1]
    c3 = kmeans.cluster_centers_[label[x, y], 2]

    因为 c1, c2, c3 对应的是数据规范化的数值,因此我们还需要进行反变换,即:

    c1=int(c1*256)-1
    c2=int(c2*256)-1
    c3=int(c3*256)-1

    然后用 img.putpixel 设置点 (x,y) 反变换后得到的特征值。最后用 img.save 保存图像。

    5. 总结

    好了,写到这关于KMeans,就要结束了。下面快速的回顾一下:

    首先,通过足球队聚类的例子引出了KMeans聚类的工作原理,简单来说两步,你可以回忆回忆。

    然后,通过KMeans实现了对图像分割的实战,另外我们还学习了如何在 Python 中如何对图像进行读写,具体的代码如下,上文中也有相应代码,你也可以自己对应下:

    import PIL.Image as image
    # 得到图像的像素值
    img = image.open(f)
    # 得到图像尺寸
    width, height = img.size

    这里会使用 PIL 这个工具包,它的英文全称叫 Python Imaging Library,顾名思义,它是 Python 图像处理标准库。同时我们也使用到了 skimage 工具包(scikit-image),它也是图像处理工具包。用过 Matlab 的同学知道,Matlab 处理起图像来非常方便。skimage 可以和它相媲美,集成了很多图像处理函数,其中对不同分类标识显示不同的颜色。在 Python 中图像处理工具包,我们用的是 skimage 工具包。

    好了,KMeans的故事就到这里吧。

    参考:

    • http://note.youdao.com/noteshare?id=10dac8bb5d83358ffe73c792e1490a7b&sub=C7A3E74A1088435ABBE11AB91AC37194
    • https://time.geekbang.org/
    • 91bf50388acc47157a80bab0c9cef08f.png

    点个在看,么么哒!

    4b2e4f7ad525c7c821046d29a9a1c916.gif
    展开全文
  • 使用聚类算法(Kmeans)进行数据降维并作为分类算法逻辑回归(logistic Regression)的数据预处理步骤实战 目录 使用聚类算法(Kmeans)进行数据降维并作为分类算法逻辑回归(logistic Regression)的数据预处理...

    使用聚类算法(Kmeans)进行数据降维并作为分类算法逻辑回归(logistic Regression)的数据预处理步骤实战

    目录

    展开全文
  • 聚类算法-KMeans

    2021-01-18 17:11:37
    KMeans的原理3.1 相关概念3.2 几个公式3.3 KMeans是否损失函数3.4 聚类算法的模型评估指标3.4.1 关于CCS参数3.4.2 样本标签已知的模型评估3.4.3 样本标签未知的模型评估 1. 概述 聚类算法属于无监督学习(即进行...
  • 聚类算法kmeans

    千次阅读 2014-11-17 21:14:28
    FreeBookSpot4485本免费的E-BOOKS分成96个类别,多达71,97 GB。 您可以在类別搜寻找和下载免费的书,如:科学、设计、编码、小说和许多其他的书。您可以在类别搜寻和下载免费的书,如:科学、设计、编码、小说和许多...
  • 聚类算法kmeanskmeans++讲解

    千次阅读 2017-12-03 21:06:37
    2、kmeans++因为,kmeans的初始种子的随机找的,这样,算法的收敛快慢与初始值关系非常大,于是,kmeans++ 主要针对初始值的选取进行改进。 初始值选取,如下:1、也是随机选取一个种子; 2、计算其他点到这
  • 首先说一下分类和聚类的区别: 分类分类其实就是从特定的数据中挖掘模式,做出相对应的判断。例如对班级的学生进性性别的分类,我事先...KMeans算法是聚类中最常用最普遍的一种算法,该算法最大的特点就是简单,易于
  • 【机器学习与算法】用python实现KmeansKmeans++算法背景K-means算法python代码结果对比 背景 K-Means算法因其算法简单,收敛快等特点而成为最常用的无监督学习方法之一,K-means算法过程如下: 随机选取K个中心点...
  • 聚类算法是web智能中很重要的一步,可运用在社交,新闻,电商等各种应用中,我打算专门开个分类讲解聚类各种算法的java版实现。 首先介绍kmeans算法kmeans算法的速度很快,性能良好,几乎是应用最广泛的,它...
  • 1 聚类算法简介 聚类算法在现实中的应用 - 用户画像,广告推荐,Data Segmentation,搜索引擎的流量推荐,恶意流量识别 ...- 聚类算法与分类算法最大的区别:聚类算法是无监督的学习算法,而分类算法属于监督的
  • 原 机器学习sklearn19.0聚类算法——Kmeans算法 2017年12月17日 ...
  • 1.基于用户的协同滤波算法 在我的前一篇文章中我介绍了一种基于用户喜好和...这次我来介绍一种将遗传算法Kmeans结合的电影推荐算法。 我们知道基于用户的协同滤波算法是一种十分热门的算法。这种算法的目的是...
  • kmeans 分类算法 聚类

    2009-06-09 22:11:31
    可以运行老师的例子,结果和别人对过, 可以采用多种输入,这个程序可以定很多点 可以研究k-means算法性能
  • KMeans算法 一、 输入参数 n_clusters:数据集将被划分成 n_clusters个‘簇’即k值以及(int, optional, default: 8)。一般需要选取多个k值进行运算,并用评估标准判断所选k值的好坏,以获得较好的聚类效果。 max_...
  • 聚类算法KMEANS原理介绍 ... KMeans算法的基本思想是初始随机给定K个簇中心,按照最邻近原则把待分类样本点分到各个簇,然后按照平均法重新计算各个簇的质心,从而确定簇心,一直迭代,知道...
  • 介绍 首先要知道为什么要聚类? 简来说:就是没有目标值,自己创造目标值 复杂说:通常聚类是做在分类之前的...聚类算法Kmeans的步骤(过程): ps:先假设此时1000个样本(点),要将其划分为3个类别(k=3)...
  • 文章目录KMeans聚类算法前言※ 聚类与分类的区别※ sklearn.cluster: Clustering --- 聚类模块一、KMeans工作原理1.定义2.算法过程3.聚类结果分析4.簇内平方和5.KMeans算法的时间复杂度(了解)二、KMeans类的使用◐ ...
  • 聚类算法-kmeans

    2018-05-22 17:30:52
    K-means(k均值)算法 k-means是划分方法中较经典的聚类算法之一。由于该算法的效率高,所以在对大规模数据进行聚类时被广泛应用。目前,许多算法均围绕着该算法进行扩展和改进。 k-means算法以k为参数,把n个样本...
  • 聚类算法KMeans

    2021-09-05 17:31:38
    聚类算法KMeans1. 算法1.1. 算法步骤1.2. 复杂度2. 优缺点3. 算法调优 & 改进3.1. 数据预处理3.2. 合理选择 K 值3.3. 采用核函数3.4. K-Means++3.5. KMeans代码3.6. ISODATA4. 收敛证明 K-means 是我们最常用的...
  • 算法KMeans(K-均值)

    千次阅读 2017-04-07 19:54:12
    今天学习了下Kmeans算法KMeans算法属于无监督学习的一种,主要通过不断迭代center中心点来使得cast损失函数最小化,即在方差最小的准则下进行不断迭代,当cast与上一次的迭代结果相同则终止迭代。但同时KMeans也...
  • 机器学习算法之K均值算法(KMeans)

    千次阅读 2019-09-28 00:32:45
    常见的聚类算法,属于非监督学习。 算法步骤 假设我们现在数据集 D D D : D = { x 1 , x 2 , . . . , x m } D=\{ x_1, x_2, ..., x_m\} D = { x 1 ​ , x 2 ​ , . . . , x m ​ } 随机选择 k k ...
  • 聚类算法 k-means
  • 怎样用matlab实现多维K-means聚类算法小编觉得一个好的周末应该是这样的:睡到中午醒来,在床上躺着玩两个小时...怎样用matlab实现多维k-means聚类算法function [ labels ] = kmeans_clustering( data, k ) [num,~]...
  • 分类是指将数据归于一系列已知类别之中的某个类的分类过程分类作为一种监督学习方法要求必须事先明确知道各个类别的信息并且断言所有待分类项都一个类别与之对应但是很多时候上述条件得不到满足尤其是在处理海量...
  • (supervised learning),其训练样本是带标记信息的,并且监督学习的目的是:对带标记的数据集进行模型学习,从而便于对新的样本进行分类。而在“无监督学习”(unsupervised learning)中,训练样本的标记信息是...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 12,852
精华内容 5,140
关键字:

常见的分类算法有kmeans