《机器学习(周志华)》学习笔记(九)

Q:分类和聚类有什么不同?

两者的区别可以主要从两个方面看出。第一,它们面对的根本问题不同。分类的根本问题是判断给定的某一个样本属于那一个类别;聚类的根本问题是探索给定的数据集可以分成哪几种类别。第二,两者使用的训练数据集有差异。分类任务使用的训练数据集中每个样本除了有属性数据外,还必须有一个标记值,用以表示该样本属于哪一类;聚类任务的数据集中每个样本可以只有属性值,没有标记值(当然也可以有)。这也可以认为是我们常说的,监督学习与无监督学习。

Q:聚类的一般方法有哪些?

聚类算法多种多样,但是万变不离其宗,最基本的思想还是先提出一中衡量样本之间相似程度的的手段,如距离、相关系数等,然后逐一计算数据集中各样本之间的相似度,尽量把相似度高的样本放到同一类。

一般来说聚类算法有三类:基于原型的聚类、基于密度的聚类、和基于层次的聚类。当然,还可以有更多,比如混合高斯模型也能用于聚类任务。

Q:衡量样本间相似度的指标有那些?

所谓样本,其数学本质就是向量。所以样本间的相似度常用距离来表示。

最简单的距离就是内积距离

向量x与y的内积

最直观的距离则是欧氏距离
欧氏距离

更一般的距离有明可夫斯基距离,其中p值视情况而定
明可夫斯基距离

上面提到的距离都是适用于有序属性的。所谓有序属性,就是指属性的取值有大小之分。比如西瓜的“含糖率”这个属性,0.1就比0.9要小。无序属性这位是指属性取值无大小之分的属性。比如西瓜的“颜色”属性,取“0”表示浅绿、取“1”表示深绿,但不能说0比1小,“颜色”属性的取值不能比较大小。此时,要更亮无序属性的距离要用到VDM距离,即

所以,对于属性中既含有有序属性,又含有无序属性的样本,则需要统一明可夫斯基距离和VDM距离
能用于有序和无序属性的统一距离公式

Q:k-means聚类算法的思路是怎样的?

当我们去考察一堆数据的时候,一般会通过平均数和方差来获取一个大致的了解。也就是说,平均数和方差可以代表一组数据。那么我们就会想,有没有一个均值向量可以代表一组向量?

自然是有的(反正概念什么的都是人定的)。


均值向量

上式代表C_i类中所有向量的均值向量。

那么,如果有k个均值向量,就代表有k个类。可以分别计算某个向量与这k个均值向量的距离,哪个距离更短,就将该向量(样本)归到哪一类。这便是k-means(k均值)算法的基本思想。

实际的算法过程是一个循环。首先人为设定k值大小,即要划分多少个类。然后第一轮在数据集中随机挑选k个样本作为初始的均值向量,接着计算剩下的样本与这几个均值向量的距离,并且聚类,可以得到k个类别,每个类别至少一个样本。此时重新计算各个类别的均值向量,得到k个新的均值向量。下面重新计算距离,再度分类,再度重新计算均值向量,得到k个新的均值向量,如此循环往复,直到得到的k个均值向量与上一轮的均值向量一样,也就是两轮的聚类结果一样的时候,循环结束。


Q:虽说聚类术语无监督学习,不需要用到样本标记信息,但是既然存在标记信息,可不可以利用一下?

LVQ(学习向量量化)算法就是利用样本标记信息来辅助聚类的算法。LVQ算法利用和k-means的均值向量类似的代表性向量(也可以叫原型向量),同样也使用距离计算然后根据最短距离分类的的思想。不过LVQ算法的目的不是直接得到划分好的几个类,而是得到t个原型向量。也就是说,LVQ的输出是t个原型向量。先上一张抽象的算法流程

LVQ算法

LVQ算法同样人为设定一个t值,也就是要划分的类别数。然后初始化t个原型向量——不是像k-means一样随便选,而是根据预先说好了的标记,在随便选。比如预先说好要选3个好瓜,2个坏瓜,就从好瓜中随便选三个,坏瓜中随便选两个。

选好初始原型向量后,开始和k-means一样不断循环计算距离,不过LVQ每次都是随机抽取训练数据集的一个样本,计算抽到的样本和各个原型向量的距离。距离最短的一个原型向量,如果其标记和抽到的标记一样,就“使原型向量向抽到的样本向量靠近”,如果其标记和抽到的标记不同,就“使原型向量向抽到的样本向量远离”——


调整原型向量

学习率,人为设定,会影响算法运行质量和时间

如此循环往复直到达到最大循环次数,或者原型向量的调整幅度已经小于某个阀值。

Q:有没有不是基于原型向量的聚类算法?

除了基于原型向量的聚类算法,还有基于密度的聚类算法,如DBSCAN,和基于层次的聚类算法,如AGNES

在了解什么是基于密度的算法前,先参考一下人际社交的生活经验。“物以类聚,人以群分”,人群中会自发地诞生多个人际关系圈子。圈子中的核心人物一般来说往往是人脉最丰富的,或者直接说认识人最多的,这些人暂且称为社交领袖。一个人一般来说可以很迅速地和自己的朋友建立联系。只要两个人处于同一个圈子之中,或者说他们处于不同的圈子,但是两个圈子的人有交集,那么即使他们不认识,也可以通过朋友的朋友的朋友······建立联系。弱两个人分属不同的圈子,且两个圈子没有交集,但是两个圈子都和第三个圈子有交集,那么这两个人同样可以通过朋友的朋友的朋友······建立联系。

根据上面这个例子,我们可以建立一个样本密度模型



DBSCAN算法中的簇类比于交际关系里的圈子,邻域类比于一个人的朋友圈,核心对象类比于社交领袖,密度直达、可达、相连分别类比于三种人与人知啊今建立联系的方式。DBSCAN算法中的一个簇是指所有可以相互之间密度直达、可达、相连的样本的集合。

而DBSCAN算法的原理也就很简单了,首先确定数据集中所有核心对象,然后随机从一个核心对象出发找出所有与之密度可达的样本,找完以后这些样本就是一个簇了,然后再随机选一个不在现有的簇范围内的核心对象,继续上面的步骤,知道所有核心对象都被分到某个簇中。

DBSCAN算法最后可能会产生几个不在任何簇里的样本,他们被称为噪声,同时也可以视为异常数据

基于层次的聚类算法试图用自顶向下或者自底向上的方式在不同层次上对数据进行划分。AGNES算法是一中自底向上的算法。算法的基本思想是在一开始把所有样本都看作一个簇类。那么有n个样本的数据集就有n个初始簇。接下来两两计算簇间距离,距离最小的两个簇合并为一个簇(有点像霍夫曼树的子树合并),直到所有的簇合并为一个簇为止。各种簇间距离计算公式如下,视情况挑选



AGNES算法最终得到的结果如下图



我们可以通过选择簇间距离来确定到底分几个簇。簇间距离越大,得到的簇越少,簇间距离越小,得到的簇越多。

Talk is cheap, show me the code!

下面是一个KMeans模型的简单实现

"""
K-means clustering model

:file: supervised.py
:author: Richy Zhu
:email: rickyzhu@foxmail.com
"""
import numpy as np

class MyKMeans:
    def __init__(self, k=3):
        '''
        K-means clustering model

        :k: int, number of clusters
        '''
        self.k = k
        self.X = None
        self.labels = None
        self.cluster_centers = None
    
    def fit(self, X):
        '''
        Train the K-means clustering model

        Parameters
        ----------
        X: ndarray of shape (m, n)
            sample data where row represent sample and column represent feature

        Returns
        -------
        self
            trained model
        '''
        ran_index = np.random.choice(np.arange(0,len(X)), self.k)
        centres = [X[i] for i in ran_index]
        prev_labels = np.zeros(len(X))
        i = 0
        while True:
            labels = []
            for x in X:
                labels.append(np.argmin([np.linalg.norm(x - c) for c in centres]))
            if np.array_equal(prev_labels, labels):
                break
            prev_labels = labels
            for i in range(len(centres)):
                centres[i] = np.mean(X[np.array(labels)==i], axis=0)
            i += 0
        self.labels = np.array(labels)
        self.cluster_centers = np.array(centres)
        return self
    
    def predict(self, X):
        '''
        Make prediction by the trained model.

        Parameters
        ----------
        X: ndarray of shape (m, n)
            data to be predicted, the same shape as trainning data

        Returns
        -------
        C: ndarray of shape (m,)
            Predicted class label per sample.
        '''
        labels = []
        for x in X:
            labels.append(np.argmin([
                np.linalg.norm(x - c) for c in self.cluster_centers
            ]))
        return np.array(labels)

测试代码如下

import numpy as np
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split

from unsupervised import *

X, y = load_iris(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y)

print('\nK-means clustering')
print('---------------------------------------------------------------------')
mykm = MyKMeans(k=3)
mykm.fit(X_train)
print('My KMeans:')
print(mykm.cluster_centers)
print(mykm.predict(X_test))
print()

from sklearn.cluster import KMeans
skkm = KMeans(n_clusters=3)
skkm.fit(X_train)
print('Sk KMeans:')
print(skkm.cluster_centers_)
print(skkm.predict(X_test))

测试结果为

$ python unsupervised_examples.py
K-means clustering
---------------------------------------------------------------------
[[4.78333333 3.11666667 1.50555556 0.26666667]
 [6.24       2.87866667 4.90133333 1.66933333]
 [5.25789474 3.74210526 1.49473684 0.26315789]]
[2 1 2 1 2 1 2 1 1 0 1 1 1 1 0 1 1 1 0 0 0 1 0 1 1 0 2 1 1 2 1 1 1 0 0 1 1
 0]

Sk KMeans:
[[5.025      3.46388889 1.45833333 0.24166667]
 [6.78888889 3.08888889 5.72962963 2.08888889]
 [5.91428571 2.75510204 4.40612245 1.42653061]]
[0 1 0 1 0 2 0 2 2 0 1 1 2 2 0 1 1 2 0 0 0 2 0 1 1 2 0 2 1 0 1 2 2 2 0 2 1
 0]

更多代码请参考https://github.com/qige96/programming-practice/tree/master/machine-learning


本作品首发于简书博客园平台,采用知识共享署名 4.0 国际许可协议进行许可。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,825评论 4 377
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,887评论 2 308
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 112,425评论 0 255
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,801评论 0 224
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,252评论 3 299
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,089评论 1 226
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,216评论 2 322
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 31,005评论 0 215
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,747评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,883评论 2 255
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,354评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,694评论 3 265
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,406评论 3 246
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,222评论 0 9
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,996评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,242评论 2 287
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 36,017评论 2 281

推荐阅读更多精彩内容