以下是我的学习笔记,以及总结,如有错误之处请不吝赐教。
本文主要介绍聚类以及K均值算法的推倒过程,最后有相关代码案例。
说到聚类就不得不先说说机器学习的分类。
机器学习主要分为三类:
监督学习:分类、回归...
无监督学习:聚类、降维...
强化学习。
下面这张图是机器学习python库sklearn的一个分类:
聚类的作用主要分为三个:
- 组织数据
- 降维
- 数据预处理,为下部数据的处理做准备
聚类的应用主要包括:
- 网页搜索
- 生物技术
- 社交网络(如facebook、twitter等等)
- 商品推荐系统(划重点)
- 天文
- 等等
输入:两个点之间的距离d(x)
输出:数据类别归属
聚类基本的三类算法:
下面重点说K-means。
目标函数:最小化点到中心点的距离平方。公式如下:
时间复杂度:属于NP hard(在非确定图灵机上无法解决(量子计算机))
先看几个特例:
- K=1时的算法:
- d=1时:需要用到动态规划来计算。
K-means实现常用的几种算法:
- 通用的The Lloyd‘s算法,即通过两个迭代循环,第一层循环:求得到中心点的距离最近的点,第二层循环:求点到中心点的均值,不断循环迭代。
但是对于这种算法,初始点的选择是需要重点考虑的,初始化的方法主要有以下几点:
- 随机初始化,即随机挑选点:
最后聚类得到:
但是容易遇到这种问题:
我们假设数据分布是随机独立分布,那么所有数据被分到正确的类的概率为:,约等于:
,概率随着k的增大呈指数级别减小。
- 最远点初始化,即找到距离前一个点最远点作为初始化点:
但是最远点也有问题:
- D2sampling:是目前最好的初始化方法,即加权重的最远点,也就是常说的K-means++,这个方法既可以保证随机初始化无法找到所有类的问题,又可以避免最远点的问题。具体的公式如下:
最关键的是,这个算法的时间复杂度并没有增加为:线性O(nkd),其中n为数据点个数,k为聚类中心点个数,d为数据集的维度。即初始化的复杂度可以忽略。
下面说说如何选择k值:
- cross_validation 将数据集分为训练集和测试集,选择在训练集效果最好的k值即可。
- elbow's method 找到k值下降斜率的拐点。
- 层次聚类,是聚类的另一个方法,他的不同类别有不同层次,类似于树状。他主要分为以下两类:
- 自上而下
- 自下而上
自下而上有三种计算两个类距离的方法:
- single linkage
- complete linkage
- average linkage
这个算法的时间复杂度较高,为:O(n3),当然通过优先队列的数据结构可以降到O(n2logn)。
最重点的来了,K-means代码实现如下:
import os, sys
import argparse
import numpy as np
import time
# Vanilla K-means clustering.
samples = np.vstack([samples1, samples2, samples3])
rorder = np.arange(num_pts * 3)
rorder = np.random.shuffle(rorder)
samples = samples[rorder, :].squeeze()
# Lloyd's algorithm, with random initialization.
k = 3
centers = np.random.rand(k, 2)
num_iters = 10
losses = []
# Save for repeated use.
xdist = np.sum(samples * samples, axis=1)
for _ in xrange(num_iters):
# Compute distance to each center.
cdist = np.sum(centers * centers, axis=1)
consts = xdist[:, np.newaxis] + cdist
dists = consts - 2 * np.dot(samples, centers.T) #计算到中心点距离
# Compute cluster assignment.
ids = np.argmin(dists, axis=1) #新的中心点迭代
losses.append(np.sum(np.min(dists, axis=1)))
for i in xrange(k):
centers[i, :] = np.mean(samples[ids == i], axis=0)
具体可以看这里:欢迎关注我的github
未完,待续。