[Python] [机器学习] 基础聚类算法(K-means、AHC、DBSCAN)简介及可视化代码

之前写的入门级介绍,有点久远有些ref找不着了

简介

  • 根据在数据中发现的描述对象及其关系的信息,将数据对象分组。
  • 对大量未知标注的数据集,按数据的内在相似性将数据集划分为多个类别,使类别内的数据相似度极大而类别间的数据相似度极小。

目标

  • 组内的对象相互之间是相似的,不同组中的对象是不同的。

作用

  1. 易于理解

    ?生物学:界门纲目科属种

    ?信息检索:搜索引擎返回结果分类

    ?商业:对客户进行分类

  2. 更加实用

    ?降维:样本数的降维、特征数的降维

    ?发现最近邻:减少计算量

类型

分类 解释
层次的
v s vs vs
划分的
层次的: 嵌套的,树状,可在不同层次上得到不同数目的类别。
划分的: 非嵌套的。每个样本恰在一个子集中。
互斥的
v s vs vs
重叠的
v s vs vs
模糊的
互斥的: 每个样本仅在一个类中。
重叠的: 一个样本可同时属于多个类。
模糊的: 每个样本以0(绝对不属于)和1(绝对属于)之间的权值属于每个类。
完全的
v s vs vs
部分的
完全的: 每个样本至少属于一个类。
部分的: 部分样本不属于任何一个类,如噪声、离群点等。

聚类vs分类

import random
import matplotlib.pyplot as plt
import pandas as pd
from sklearn import datasets
from pandas import DataFrame

# 造数据
# 圈圈
noisy_circles=datasets.make_circles(n_samples=1000,factor=.5,noise=.05)
circle = DataFrame()
circle['x1'] = noisy_circles[0][:,0]
circle['x2'] = noisy_circles[0][:,1]
circle['label'] = noisy_circles[1]
# 堆堆
def random_sample(num, mean, st):
    '''
    num:个数
    mean:均值
    st:标准差
    '''
    sample = []
    i = 0
    while i < num:
        sample.append(random.gauss(mean, st))
        i += 1
    return sample
    
num = 300
sample_0 = pd.DataFrame({
   'x1':random_sample(num, 4, 0.5), 'x2': random_sample(num, 4, 0.5), 'y': [0 for i in range(num)]})
sample_1 = pd.DataFrame({
   'x1':random_sample(num, 2, 0.5), 'x2': random_sample(num, 2, 0.5), 'y': [1 for i in range(num)]})
sample = pd.concat([sample_0, sample_1])

# 聚类vs分类
plt.figure(figsize=(16,8))
plt.subplot(1,2,1)
plt.scatter(sample_0['x1'], sample_0['x2'], marker = 'o', c = 'k')
plt.scatter(sample_1['x1'], sample_1['x2'], marker = 'o', c = 'k')
plt.title('聚类(无监督)', fontsize =25)

plt.subplot(1,2,2)
plt.scatter(sample_0['x1'], sample_0['x2'], marker = 'o', c = 'b')
plt.scatter(sample_1['x1'], sample_1['x2'], marker = 'o', c = 'r')
plt.title('分类(有监督)', fontsize =25)
plt.show()

在这里插入图片描述

K-means

[K-means] 伪代码

#####################################

  1. 选择 k k k个点作为初始质心。
  2. repeat
  3. ​ 将每个点指派到最近的质心,形成 k k k个簇。
  4. ​ 重新计算每个簇的质心。
  5. until 质心不发生变化。

#####################################

[K-means] 过程详解

ref: GitHub: snippet-code

# 修改
data = sample
repeat = 20

# ================开始================
# 导入数据
points = [[data.iloc[i].x1, data.iloc[i].x2] for i in range(len(data))]

# 初始质心
currentCenter1 = [data.x1.min() + (data.x1.max()-data.x1.min())*random.random(), data.x1.min() + (data.x2.max()-data.x2.min())*random.random()]
currentCenter2 = [data.x1.min() + (data.x1.max()-data.x1.min())*random.random(), data.x1.min() + (data.x2.max()-data.x2.min())*random.random()]

# 记录每次迭代后每个簇的质心的更新轨迹
center1 = [currentCenter1]; center2 = [currentCenter2]

# 丢点图
plt.figure(figsize=(18,18))
ax = plt.subplot(3,3, 1)
change_ax(ax)
plt.title('step 0', fontsize = 15)
plt.plot([eachpoint[0] for eachpoint in points], [eachpoint[1] for eachpoint in points], '.', color='grey')
plt.scatter([eachcenter[0] for eachcenter in center1], [eachcenter[1] for eachcenter in center1], marker='x', c='b', s=100)
plt.scatter([eachcenter[0] for eachcenter in center2], [eachcenter[1] for eachcenter in center2], marker='x', c='g', s=100)

# 两个簇
group1 = []; group2 = []

for runtime in range(repeat):
    group1 = []; group2 = []
    for eachpoint in points:
        # 计算每个点到质心的距离
        distance1 = pow(abs(eachpoint[0]-currentCenter1[0]),2) + pow(abs(eachpoint[1]-currentCenter1[1]),2)
        distance2 = pow(abs(eachpoint[0]-currentCenter2[0]),2) + pow(abs(eachpoint[1]-currentCenter2[1]),2)
        
        # 将该点指派到离它最近的质心所在的簇
        mindis = min(distance1,distance2)
        if(mindis == distance1):
            group1.append(eachpoint)
        else:
            group2.append(eachpoint)
            
    if runtime < 5 or runtime > (repeat - 4): 
    	# 只可视化前五次最后三次
        if runtime < 5:
            ax = plt.subplot(3,3, runtime+2)
            change_ax(ax)
            plt.title('step %d'%(runtime+1), fontsize = 15)
        else:
            ax = plt.subplot(3,3, 10-repeat+runtime)
            change_ax(ax)
            plt.title('step %d'%(runtime+1), fontsize = 15)
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值