一、聚类分析

  • 无监督学习算法中最常用的一类
  • 聚类是将数据分类到不同的或者这样的一个过程,所以同一个簇中的对象有很大的相似性,而不同簇间的对象有很大的相异性
  • 聚类与分类的不同在于,聚类所要求的划分的类是未知的。

二、常见的聚类算法

  • K-Means聚类
  • 层次聚类
  • DBSCAN

三、K-均值聚类算法

1.定义

  是一种迭代求解的聚类分析算法

2.工作流程
  • 随机确定K个初始点作为质心,K为用户给定值
  • 为每个点找距其最近的质心,并将这些点分别分配给该质心所对应的的簇或类
  • 每个簇的质心更新为该簇所有点的平均值
3.伪代码
创建k个点作为起始质心(经常是随机选择)
当任意一个点的簇分配结果发生改变时
   对数据集中的每个数据点
       对每个质心
           计算质心与数据点之间的距离
       将数据点分配到距其最近的簇
   对每一个簇,计算簇中所有点的均值并将均值作为质心
4.Python实现
引包:
import pandas as pd
import numpy as np
读取数据

数据地址:

链接:https://pan.baidu.com/s/1vtmvoTb6g2ZUQOzjTFjkRQ
提取码:zy1m

dataSet = pd.read_csv('iris.txt', header = None)
计算距离函数

  计算距离的方法有很多,这里使用的是最简单的欧氏距离

def calDist(arrA, arrB):
	"""
	计算欧式距离,返回一个点到各个质心的距离
	arrA --> ndarray
	arrB --> ndarray
	return --> ndarray 
	"""
    d = arrA - arrB
    s = (np.sum(np.power(d, 2), axis=1))
    dist = np.sqrt(s.tolist())
    return dist
选取随机质心函数

  虽然可以随机选取质心,但如果选取不在点所在区域的质心,会加大计算量,并使结果误差较大。所以再好从每列数值范围内选取质心。

def randCent(dataSet, k):
	"""
	
	"""
    n = dataSet.shape[1]
    min = dataSet.iloc[:, :n - 1].min()
    max = dataSet.iloc[:, :n - 1].max()
    randCent = np.random.uniform(min, max, (k, n - 1))
    return randCent
KMeans聚类算法

本质上就是一个不断计算距离并迭代质心的过程。其中:
centroids

def KMeans(dataSet,k,distMeas = calDist,createCent = randCent):
	"""
	:param dataSet: 数据集
    :param k: 指定质心个数
    :param distMeas : 欧氏距离计算函数
    :param corids: 随机质心选取函数
    :return: centroids--> 质心 ndarray
    		 result_set --> 分类结果 DataFrame
	"""
    m,n = dataSet.shape
    centroids = createCent(dataSet,k)
    clusterAssment = np.zeros((m,3))  # 创建一个容器,分别存放距离,该次所属质心,上一次所属质心
    clusterAssment[:,0] = np.inf
    clusterAssment[:,1:3] = -1
    result_set = pd.concat([dataSet,pd.DataFrame(clusterAssment)],axis=1,ignore_index=True)
    clusterChanged = True 
    
    while clusterChanged:
        clusterChanged = False
        for i in range(m):
            dist = distMeas(dataSet.iloc[i,:n-1].values,centroids)
            result_set.iloc[i,n] = dist.min()
            result_set.iloc[i,n+1] = np.where(dist == dist.min())[0]
        clusterChanged = not(result_set.iloc[:,-1] == result_set.iloc[:,-2]).all() # 终止条件:每一个点所属质心不再改变
        if clusterChanged:
            cent_df = result_set.groupby(n+1).mean() # 使用平均值代替质心
            centroids = cent_df.iloc[:,:n-1].values
            result_set.iloc[:,-1] = result_set.iloc[:,-2] # 将此次质心分类存储,与下一次迭代对比
    return centroids,result_set
5.使用场景

K-Means聚类算法:

  • 优点:容易实现
  • 缺点:可能收敛到局部最小值,在大规模数据集上收敛较慢
  • 使用数据类型:数值型数据

参考资料:《机器学习实战》-- Peter Harrington
      菊安酱的机器学习