机器学习-聚类算法

news2025/8/16 12:46:49

机器学习-基础知识
机器学习-线性回归
机器学习-逻辑回归
机器学习-聚类算法
机器学习-决策树算法
机器学习-集成算法
机器学习-SVM算法

文章目录

    • 聚类算法
      • 1. K-Means算法
        • 1.1. 理论基础
        • 1.2. 具体代码
          • 1.2.1. 数据集
          • 1.2.2. 自定义k-means算法类
          • 1.2.3. 测试模块
        • 1.3. 效果展示
          • 1.3.1. 有标签和无标签数据集
          • 1.3.2. 无标签与训练结果对比
      • 2. DBSCAN算法
        • 2.1. 理论基础
      • 3. 聚类算法实践
        • 3.1. Kmeans
        • 3.2. 决策边界
        • 3.3. 算法流程
        • 3.4. 不稳定的结果
        • 3.5. 评估方法
        • 3.6. 找到最佳簇数
        • 3.7. 轮廓系数
        • 3.8. Kmeans存在的问题
        • 3.9. 图像分割小例子
        • 3.10. 半监督学习
        • 3.11. DBSCAN算法

聚类算法

1. K-Means算法

1.1. 理论基础

  • k-means算法是聚类算法的一种,属于无监督学习算法,训练样本的标记信息是未知的,目标是通过对无标记样本的学习来揭示数据的内在性质和规律,为进一步数据分析提供基础。

  • 核心步骤有两点:

    1. 距离的计算;
    2. 中心点的更新。
  • 基本概念:

    • :就是分类的数量,需要指定;

    • 质心:均值,就是向量各维取平均;

    • 距离的度量:常用欧几里得距离和余弦相似度;

    • 优化目标
      E = ∑ i = 1 k ∑ x ϵ C i ∣ ∣ x − μ i ∣ ∣ 2 2 E= \sum_{i=1}^{k}\sum_{x\epsilon C_i}{||x-\mu_i||}_2^2 E=i=1kxϵCixμi22

  • 工作流程
    在这里插入图片描述

  • 优点:

    简单,快速,适合常规数据集 。

  • 缺点:

    1. K值难确定;
    2. 复杂度与样本呈线性关系;
    3. 很难发现任意形状的簇。

    例如下面这种数据集,使用K-Means算法很难区分开,像以下的这种数据集,应当使用DBSCAN算法。
    在这里插入图片描述

1.2. 具体代码

1.2.1. 数据集

(iris.csv)

sepal_length,sepal_width,petal_length,petal_width,class
5.1,3.5,1.4,0.2,SETOSA
4.9,3.0,1.4,0.2,SETOSA
4.7,3.2,1.3,0.2,SETOSA
4.6,3.1,1.5,0.2,SETOSA
5.0,3.6,1.4,0.2,SETOSA
5.4,3.9,1.7,0.4,SETOSA
4.6,3.4,1.4,0.3,SETOSA
5.0,3.4,1.5,0.2,SETOSA
4.4,2.9,1.4,0.2,SETOSA
4.9,3.1,1.5,0.1,SETOSA
5.4,3.7,1.5,0.2,SETOSA
4.8,3.4,1.6,0.2,SETOSA
4.8,3.0,1.4,0.1,SETOSA
4.3,3.0,1.1,0.1,SETOSA
5.8,4.0,1.2,0.2,SETOSA
5.7,4.4,1.5,0.4,SETOSA
5.4,3.9,1.3,0.4,SETOSA
5.1,3.5,1.4,0.3,SETOSA
5.7,3.8,1.7,0.3,SETOSA
5.1,3.8,1.5,0.3,SETOSA
5.4,3.4,1.7,0.2,SETOSA
5.1,3.7,1.5,0.4,SETOSA
4.6,3.6,1.0,0.2,SETOSA
5.1,3.3,1.7,0.5,SETOSA
4.8,3.4,1.9,0.2,SETOSA
5.0,3.0,1.6,0.2,SETOSA
5.0,3.4,1.6,0.4,SETOSA
5.2,3.5,1.5,0.2,SETOSA
5.2,3.4,1.4,0.2,SETOSA
4.7,3.2,1.6,0.2,SETOSA
4.8,3.1,1.6,0.2,SETOSA
5.4,3.4,1.5,0.4,SETOSA
5.2,4.1,1.5,0.1,SETOSA
5.5,4.2,1.4,0.2,SETOSA
4.9,3.1,1.5,0.1,SETOSA
5.0,3.2,1.2,0.2,SETOSA
5.5,3.5,1.3,0.2,SETOSA
4.9,3.1,1.5,0.1,SETOSA
4.4,3.0,1.3,0.2,SETOSA
5.1,3.4,1.5,0.2,SETOSA
5.0,3.5,1.3,0.3,SETOSA
4.5,2.3,1.3,0.3,SETOSA
4.4,3.2,1.3,0.2,SETOSA
5.0,3.5,1.6,0.6,SETOSA
5.1,3.8,1.9,0.4,SETOSA
4.8,3.0,1.4,0.3,SETOSA
5.1,3.8,1.6,0.2,SETOSA
4.6,3.2,1.4,0.2,SETOSA
5.3,3.7,1.5,0.2,SETOSA
5.0,3.3,1.4,0.2,SETOSA
7.0,3.2,4.7,1.4,VERSICOLOR
6.4,3.2,4.5,1.5,VERSICOLOR
6.9,3.1,4.9,1.5,VERSICOLOR
5.5,2.3,4.0,1.3,VERSICOLOR
6.5,2.8,4.6,1.5,VERSICOLOR
5.7,2.8,4.5,1.3,VERSICOLOR
6.3,3.3,4.7,1.6,VERSICOLOR
4.9,2.4,3.3,1.0,VERSICOLOR
6.6,2.9,4.6,1.3,VERSICOLOR
5.2,2.7,3.9,1.4,VERSICOLOR
5.0,2.0,3.5,1.0,VERSICOLOR
5.9,3.0,4.2,1.5,VERSICOLOR
6.0,2.2,4.0,1.0,VERSICOLOR
6.1,2.9,4.7,1.4,VERSICOLOR
5.6,2.9,3.6,1.3,VERSICOLOR
6.7,3.1,4.4,1.4,VERSICOLOR
5.6,3.0,4.5,1.5,VERSICOLOR
5.8,2.7,4.1,1.0,VERSICOLOR
6.2,2.2,4.5,1.5,VERSICOLOR
5.6,2.5,3.9,1.1,VERSICOLOR
5.9,3.2,4.8,1.8,VERSICOLOR
6.1,2.8,4.0,1.3,VERSICOLOR
6.3,2.5,4.9,1.5,VERSICOLOR
6.1,2.8,4.7,1.2,VERSICOLOR
6.4,2.9,4.3,1.3,VERSICOLOR
6.6,3.0,4.4,1.4,VERSICOLOR
6.8,2.8,4.8,1.4,VERSICOLOR
6.7,3.0,5.0,1.7,VERSICOLOR
6.0,2.9,4.5,1.5,VERSICOLOR
5.7,2.6,3.5,1.0,VERSICOLOR
5.5,2.4,3.8,1.1,VERSICOLOR
5.5,2.4,3.7,1.0,VERSICOLOR
5.8,2.7,3.9,1.2,VERSICOLOR
6.0,2.7,5.1,1.6,VERSICOLOR
5.4,3.0,4.5,1.5,VERSICOLOR
6.0,3.4,4.5,1.6,VERSICOLOR
6.7,3.1,4.7,1.5,VERSICOLOR
6.3,2.3,4.4,1.3,VERSICOLOR
5.6,3.0,4.1,1.3,VERSICOLOR
5.5,2.5,4.0,1.3,VERSICOLOR
5.5,2.6,4.4,1.2,VERSICOLOR
6.1,3.0,4.6,1.4,VERSICOLOR
5.8,2.6,4.0,1.2,VERSICOLOR
5.0,2.3,3.3,1.0,VERSICOLOR
5.6,2.7,4.2,1.3,VERSICOLOR
5.7,3.0,4.2,1.2,VERSICOLOR
5.7,2.9,4.2,1.3,VERSICOLOR
6.2,2.9,4.3,1.3,VERSICOLOR
5.1,2.5,3.0,1.1,VERSICOLOR
5.7,2.8,4.1,1.3,VERSICOLOR
6.3,3.3,6.0,2.5,VIRGINICA
5.8,2.7,5.1,1.9,VIRGINICA
7.1,3.0,5.9,2.1,VIRGINICA
6.3,2.9,5.6,1.8,VIRGINICA
6.5,3.0,5.8,2.2,VIRGINICA
7.6,3.0,6.6,2.1,VIRGINICA
4.9,2.5,4.5,1.7,VIRGINICA
7.3,2.9,6.3,1.8,VIRGINICA
6.7,2.5,5.8,1.8,VIRGINICA
7.2,3.6,6.1,2.5,VIRGINICA
6.5,3.2,5.1,2.0,VIRGINICA
6.4,2.7,5.3,1.9,VIRGINICA
6.8,3.0,5.5,2.1,VIRGINICA
5.7,2.5,5.0,2.0,VIRGINICA
5.8,2.8,5.1,2.4,VIRGINICA
6.4,3.2,5.3,2.3,VIRGINICA
6.5,3.0,5.5,1.8,VIRGINICA
7.7,3.8,6.7,2.2,VIRGINICA
7.7,2.6,6.9,2.3,VIRGINICA
6.0,2.2,5.0,1.5,VIRGINICA
6.9,3.2,5.7,2.3,VIRGINICA
5.6,2.8,4.9,2.0,VIRGINICA
7.7,2.8,6.7,2.0,VIRGINICA
6.3,2.7,4.9,1.8,VIRGINICA
6.7,3.3,5.7,2.1,VIRGINICA
7.2,3.2,6.0,1.8,VIRGINICA
6.2,2.8,4.8,1.8,VIRGINICA
6.1,3.0,4.9,1.8,VIRGINICA
6.4,2.8,5.6,2.1,VIRGINICA
7.2,3.0,5.8,1.6,VIRGINICA
7.4,2.8,6.1,1.9,VIRGINICA
7.9,3.8,6.4,2.0,VIRGINICA
6.4,2.8,5.6,2.2,VIRGINICA
6.3,2.8,5.1,1.5,VIRGINICA
6.1,2.6,5.6,1.4,VIRGINICA
7.7,3.0,6.1,2.3,VIRGINICA
6.3,3.4,5.6,2.4,VIRGINICA
6.4,3.1,5.5,1.8,VIRGINICA
6.0,3.0,4.8,1.8,VIRGINICA
6.9,3.1,5.4,2.1,VIRGINICA
6.7,3.1,5.6,2.4,VIRGINICA
6.9,3.1,5.1,2.3,VIRGINICA
5.8,2.7,5.1,1.9,VIRGINICA
6.8,3.2,5.9,2.3,VIRGINICA
6.7,3.3,5.7,2.5,VIRGINICA
6.7,3.0,5.2,2.3,VIRGINICA
6.3,2.5,5.0,1.9,VIRGINICA
6.5,3.0,5.2,2.0,VIRGINICA
6.2,3.4,5.4,2.3,VIRGINICA
5.9,3.0,5.1,1.8,VIRGINICA
1.2.2. 自定义k-means算法类
  1. def train(self,max_iterations): 训练函数,用来训练数据集;
  2. def centroids_init(data,num_culsters): 中心点初始化,随机生成位置不确定的中心点;
  3. def centroids_find_closest(data,centroids): 计算距离,计算每个数据点到所有中心点的最短距离;
  4. def centroids_compute(data,closest_centroids_ids,num_clustres): 进行中心点的更新。
import numpy as np

class KMeans:
    def __init__(self,data,num_clusters):
        self.data = data
        # 聚成的类别
        self.num_clusters = num_clusters

    def train(self,max_iterations):
        """训练函数"""
        # 1.先随机选择k个中心点
        centroids = KMeans.centroids_init(self.data,self.num_clusters)
        # 2.开始训练
        num_examples = self.data.shape[0]
        # 最近的中心点
        closest_centroids_ids = np.empty((num_examples,1))
        for _ in range(max_iterations):
            # 3.得到当前每一个样本点到K个中心点的距离,找最近的(核心1:计算距离)
            closest_centroids_ids = self.centroids_find_closest(self.data,centroids)
            # 4.进行中心点位置更新(核心2:质心更新)
            centroids = self.centroids_compute(self.data,closest_centroids_ids,self.num_clusters)
        return centroids,closest_centroids_ids


    @staticmethod
    def centroids_init(data,num_culsters):
        """中心点初始化"""
        # 获取样本总数
        num_examples = data.shape[0]
        # 洗牌操作
        random_ids = np.random.permutation(num_examples)
        # 取出所有的中心点
        centroids = data[random_ids[:num_culsters],:]
        return centroids

    @staticmethod
    def centroids_find_closest(data,centroids):
        """计算距离"""
        # 获取样本数量
        num_examples = data.shape[0]
        # 获取中心点数量
        num_centroids = centroids.shape[0]
        closest_centroids_ids = np.zeros((num_examples,1))
        # 每一个样本点都要计算与所有簇的距离,然后返回最近的那个簇
        for example_index in range(num_examples):
            distance = np.zeros((num_centroids,1))
            for centroid_index in range(num_centroids):
                distance_diff = data[example_index,:] - centroids[centroid_index,:]
                # 对数据进行平方操作
                distance[centroid_index] = np.sum(distance_diff**2)
            # 找最近的聚类
            closest_centroids_ids[example_index] = np.argmin(distance)
        return closest_centroids_ids

    @staticmethod
    def centroids_compute(data,closest_centroids_ids,num_clustres):
        """质心更新"""
        num_features = data.shape[1]
        # 先填充质心点(矩阵)
        centroids = np.zeros((num_clustres,num_features))
        # 每一个类别都需要计算
        for centroid_id in range(num_clustres):
            # 找到属于当前类别的点
            closest_ids = (closest_centroids_ids == centroid_id)
            centroids[centroid_id] = np.mean(data[closest_ids.flatten(),:],axis = 0)
        return centroids
1.2.3. 测试模块
import pandas as pd
import matplotlib.pyplot as plt

from K_Means import KMeans

data = pd.read_csv('../data/iris.csv')
iris_types = ['SETOSA','VERSICOLOR','VIRGINICA']
# 两个特征,一个是花萼长度,一个是花萼宽度
x1_axis = 'petal_length'
x2_axis = 'petal_width'

# 原始数据图展示
plt.figure(figsize=(12,5))
plt.subplot(121)
# 分类别展示
for iris_type in iris_types:
    # 区分类别显示: [data['class'] == iris_type]
    plt.scatter(data[x1_axis][data['class'] == iris_type],
                data[x2_axis][data['class'] == iris_type],
                label = iris_type)
plt.title('label known')
plt.legend()
plt.subplot(122)
# 不区分类别显示: [:]
plt.scatter(data[x1_axis][:], data[x2_axis][:])
plt.title('label unknown')
plt.show()

# 选取两个特征进行展示
num_examples = data.shape[0]
x_train = data[[x1_axis, x2_axis]].values.reshape(num_examples, 2)

# 指定好训练所需的参数
num_clusters = 3
max_iteritions = 50

# 构建聚类算法
k_means = KMeans(x_train,num_clusters)
centroids,closest_centroids_ids = k_means.train(max_iteritions)

# 对比结果
plt.figure(figsize=(12,5))
plt.subplot(121)
for iris_type in iris_types:
    plt.scatter(data[x1_axis][data['class'] == iris_type],
                data[x2_axis][data['class'] == iris_type],
                label=iris_type)
plt.title('label known')
plt.legend()
plt.subplot(122)
for centroids_id,centroid in enumerate(centroids):
    # 当前样本索引
    current_examples_index = (closest_centroids_ids == centroids_id).flatten()
    plt.scatter(data[x1_axis][current_examples_index],
                data[x2_axis][current_examples_index],
                label=centroids_id)

for centroids_id,centroid in enumerate(centroids):
    plt.scatter(centroid[0],centroid[1],c='red',marker='X')
plt.legend()
plt.title('label kmeans')
plt.show()

1.3. 效果展示

1.3.1. 有标签和无标签数据集

左图为有标签的数据集展示,右图是无标签的数据集展示,K-means算法是无监督的学习,没有类别标记,所以训练时不能指定标签,也就是右图所示的数据形式。
在这里插入图片描述

1.3.2. 无标签与训练结果对比

左图为有标签的数据集,右图是经过k-means算法训练之后的结果演示,类别为3类,中心叉号代表每个类别的质心点。
在这里插入图片描述

2. DBSCAN算法

2.1. 理论基础

  • 核心对象:若某个点的密度达到算法设定的阈值则其为核心点(即 r 邻域内点的数量不小于 minPts)。

  • ϵ-邻域的距离阈值:设定的半径r 。

  • 直接密度可达:若某点p在点q的 r 邻域内,且q是核心点,则p-q直接密度可达。

  • 密度可达:若有一个点的序列q0、q1、…qk,对任意qi-qi-1是直接密度可达的 ,则称从q0到qk密度可达,这实际上是直接密度可达的传播。

  • 密度相连:若从某核心点p出发,点q和点k都是密度可达的 ,则称点q和点k是密度相连的。

  • 边界点:属于某一个类的非核心点,不能发展下线了。

  • 直接密度可达:若某点p在点q的 r 邻域内,且q是核心点则p-q直接密度可达。

  • 工作流程
    在这里插入图片描述

  • 优点:

    1. 不需要指定簇个数;
    2. 可以发现任意形状的簇;
    3. 擅长找到离群点(检测任务);
    4. 两个参数。
  • 缺点:

    1. 高维数据有些困难(可以做降维) ;
    2. 参数难以选择(参数对结果的影响非常大);
    3. Sklearn中效率很慢(数据削减策略)。

3. 聚类算法实践

3.1. Kmeans

  1. 导包操作

    导入numpy、matplotlib工具包,以及画图操作的相关参数设置,最后导入的包是防止环境出现警告。

import numpy as np
import os
%matplotlib inline
import matplotlib
import matplotlib.pyplot as plt

plt.rcParams['axes.labelsize'] = 14
plt.rcParams['xtick.labelsize'] = 12
plt.rcParams['ytick.labelsize'] = 12

import warnings
warnings.filterwarnings('ignore')
np.random.seed(42)
  1. 绘制中心点并设置发散程度
# 导入绘制类别的工具包
from sklearn.datasets import make_blobs

# 指定五个中心点
blob_centers = np.array(
[
    [0.2,2.3],
    [-1.5,2.3],
    [-2.8,1.8],
    [-2.8,2.8],
    [-2.8,1.3]
]
)

# 五个点对应的发散程度,应当设置的小一点
blob_std = np.array([0.4,0.3,0.1,0.1,0.1])
  1. 设置样本
# 参数n_samples:样本个数,centers:样本中心点,cluster_std:以中心点为圆心,向周围发散的程度
X,y = make_blobs(n_samples = 2000,centers=blob_centers,cluster_std=blob_std,random_state=7)
  1. 画图展示
def plot_clusters(X,y = None):
    plt.scatter(X[:,0],X[:,1],c=y,s=1)
    plt.xlabel("$x_1$",fontsize=14)
    plt.ylabel("$x_2$",fontsize=14,rotation=0)
    
plt.figure(figsize=(8,4))
# 无监督学习,传递参数的时候只传递X值
plot_clusters(X)
plt.show()
  1. 效果展示
    在这里插入图片描述

3.2. 决策边界

  1. 假定k=5进行分类
from sklearn.cluster import KMeans
k = 5
kmeans = KMeans(n_clusters = 5,random_state = 42)
# 计算聚类中心并预测每个样本的聚类索引
# fit_predict(X)与kmeans.labels_得到的结果是一致的
y_pred = kmeans.fit_predict(X)
  1. 画图展示
# 把当前的数据进行展示
def plot_data(X):
    plt.plot(X[:, 0], X[:, 1], 'k.', markersize=2)

# 绘制中心点
def plot_centroids(centroids, weights=None, circle_color='w', cross_color='k'):
    if weights is not None:
        centroids = centroids[weights > weights.max() / 10]
    plt.scatter(centroids[:, 0], centroids[:, 1],
                marker='o', s=30, linewidths=8,
                color=circle_color, zorder=10, alpha=0.9)
    plt.scatter(centroids[:, 0], centroids[:, 1],
                marker='x', s=50, linewidths=5,
                color=cross_color, zorder=11, alpha=1)

# 绘制等高线
def plot_decision_boundaries(clusterer, X, resolution=1000, show_centroids=True,
                             show_xlabels=True, show_ylabels=True):
    mins = X.min(axis=0) - 0.1
    maxs = X.max(axis=0) + 0.1
    # 棋盘操作
    xx, yy = np.meshgrid(np.linspace(mins[0], maxs[0], resolution),
                         np.linspace(mins[1], maxs[1], resolution))
    # 预测结果值          合成棋盘
    Z = clusterer.predict(np.c_[xx.ravel(), yy.ravel()])
    # 预测结果值与棋盘一致
    Z = Z.reshape(xx.shape)
    
    # 绘制等高线,并绘制区域颜色
    plt.contourf(Z, extent=(mins[0], maxs[0], mins[1], maxs[1]),
                cmap="Pastel2")
    plt.contour(Z, extent=(mins[0], maxs[0], mins[1], maxs[1]),
                linewidths=1, colors='k')
    plot_data(X)
    
    if show_centroids:
        plot_centroids(clusterer.cluster_centers_)

    if show_xlabels:
        plt.xlabel("$x_1$", fontsize=14)
    else:
        plt.tick_params(labelbottom='off')
        
    if show_ylabels:
        plt.ylabel("$x_2$", fontsize=14, rotation=0)
    else:
        plt.tick_params(labelleft='off')
        

 
# 调用函数开始绘图
plt.figure(figsize = (8,4))
plot_decision_boundaries(kmeans,X)
plt.show()
  1. 效果展示
    在这里插入图片描述

3.3. 算法流程

​ 就是看程序每一步的优化结果。

  1. 设置优化步数
# max_iter设置1/2/3相当于三步
kmean_iter1 = KMeans(n_clusters=5,init='random',n_init=1,max_iter=1,random_state=1)
kmean_iter2 = KMeans(n_clusters=5,init='random',n_init=1,max_iter=2,random_state=1)
kmean_iter3 = KMeans(n_clusters=5,init='random',n_init=1,max_iter=3,random_state=1)

kmean_iter1.fit(X)
kmean_iter2.fit(X)
kmean_iter3.fit(X)
  1. 画图展示
plt.figure(figsize=(12,10))
plt.subplot(321)
# 绘制初始点
plot_data(X)
# 绘制中心点
plot_centroids(kmean_iter1.cluster_centers_, circle_color='r', cross_color='k')
plt.title('Update cluster_centers')

plt.subplot(322)
plot_decision_boundaries(kmean_iter1, X,show_xlabels=False, show_ylabels=False)
plt.title('Iter1')

plt.subplot(323)
plot_decision_boundaries(kmean_iter1, X,show_xlabels=False, show_ylabels=False)
plot_centroids(kmean_iter2.cluster_centers_,circle_color='r',cross_color='g')
plt.title('Change1')

plt.subplot(324)
plot_decision_boundaries(kmean_iter2, X,show_xlabels=False, show_ylabels=False)
plt.title('Iter2')

plt.subplot(325)
plot_decision_boundaries(kmean_iter2, X,show_xlabels=False, show_ylabels=False)
plot_centroids(kmean_iter3.cluster_centers_,circle_color='r',cross_color='g')
plt.title('Change2')

plt.subplot(326)
plot_decision_boundaries(kmean_iter3, X,show_xlabels=False, show_ylabels=False)
plt.title('Iter3')
  1. 效果展示

    图1为最开始的数据和生成的随机点分布,图2开始进行第一次迭代,图3是进行第二次迭代的过程,其中,黑白点代表上一次中心点的位置,红绿点代表本次迭代后中心点的更新,图4是第二次迭代后的中心点的位置,图5和图6分别是第三次迭代过程和结果中心点的分布情况。
    在这里插入图片描述

3.4. 不稳定的结果

  1. 画图展示
def plot_clusterer_comparison(c1,c2,X):
    c1.fit(X)
    c2.fit(X)
    
    plt.figure(figsize=(12,4))
    plt.subplot(121)
    plot_decision_boundaries(c1,X)
    plt.subplot(122)
    plot_decision_boundaries(c2,X)
    
    
    
# 创建对象,进行不同(质心初始化的随机数生成)结果对比 
c1 = KMeans(n_clusters = 5,init='random',n_init = 1,random_state=11)
c2 = KMeans(n_clusters = 5,init='random',n_init = 1,random_state=19)
plot_clusterer_comparison(c1,c2,X)
  1. 效果展示

    不同的质心初始化的随机数生成次数,得到的结果是不稳定的。
    在这里插入图片描述

3.5. 评估方法

Inertia指标:每个样本到它最近簇的距离的平方和然后求和。

kmeans.inertia_
## 211.5985372581684
X_dist = kmeans.transform(X)
# 找到每个样本到最近的簇的距离
X_dist[np.arange(len(X_dist)),kmeans.labels_]

np.sum(X_dist[np.arange(len(X_dist)),kmeans.labels_]**2)
## 211.59853725816868

3.6. 找到最佳簇数

  1. 选择10次数据进行查找
kmeans_per_k = [KMeans(n_clusters = k).fit(X) for k in range(1,10)]
inertias = [model.inertia_ for model in kmeans_per_k]
  1. 画图展示
plt.figure(figsize=(8,4))
plt.plot(range(1,10),inertias,'bo-')
plt.axis([1,8.5,0,1300])
plt.show()
  1. 效果展示

    根据下图所示,横轴为4的时候出现拐点,意思就是根据Inertia指标评估出来的簇的个数为4,但是肉眼可见应当是5个簇比较合理,所以Inertia指标只能作为参考。
    在这里插入图片描述

3.7. 轮廓系数

在这里插入图片描述

结论:

  • s(i)接近1,则说明样本(i)聚类合理;
  • s(i)接近-1,则说明样本(i)更应该分类到另外的簇;
  • 若s(i) 近似为0,则说明样本(i)在两个簇的边界上。
  1. 计算所有样本的平均轮廓系数
from sklearn.metrics import silhouette_score
# 计算所有样本的平均轮廓系数
silhouette_score(X,kmeans.labels_)
  1. 计算所有轮廓系数
silhouette_scores = [silhouette_score(X,model.labels_) for model in kmeans_per_k[1:]]
  1. 画图展示
plt.figure(figsize=(8,4))
plt.plot(range(2,10),silhouette_scores,'bo-')
# plt.axis([1,8.5,0,1300])
plt.show()
  1. 效果展示

    下图结论:此图是上面K-Means算法对应的轮廓系数图,轮廓系数应当越大越好,从图中可以看出,当簇的个数为4时,轮廓系数的值达到最大,从实验看出,簇的个数为5,总结得出衡量指标只是一种指标,不能作为唯一的衡量标准。
    在这里插入图片描述

3.8. Kmeans存在的问题

  1. 生成原始数据集
X1, y1 = make_blobs(n_samples=1000, centers=((4, -4), (0, 0)), random_state=42)
X1 = X1.dot(np.array([[0.374, 0.95], [0.732, 0.598]]))
X2, y2 = make_blobs(n_samples=250, centers=1, random_state=42)
X2 = X2 + [6, -8]
X = np.r_[X1, X2]
y = np.r_[y1, y2]

plot_data(X)
  1. 原始数据集的效果展示
    在这里插入图片描述

  2. 默认的中心点与随机生成的中心点进行对比

kmeans_good = KMeans(n_clusters = 3,init = np.array([[-1.5,2.5],[0.5,0],[4,0]]),n_init=1,random_state=42)
kmeans_bad = KMeans(n_clusters = 3,random_state=42)
kmeans_good.fit(X)
kmeans_bad.fit(X)
  1. 绘制图形
plt.figure(figsize=(10,4))
plt.subplot(121)
plot_decision_boundaries(kmeans_good,X)
# plt.title('Good - inertia = {}'.fotmat(kmeans_good.inertia_))

plt.subplot(122)
plot_decision_boundaries(kmeans_bad,X)
# plt.title('Bad - inertia = {}'.fotmat(kmeans_bad.inertia_))
  1. 效果展示
    在这里插入图片描述

3.9. 图像分割小例子

  1. 加载图片
# ladybug.png
from matplotlib.image import imread
image = imread('ladybug.png')
image.shape
  1. 重塑数据
X = image.reshape(-1,3)
  1. 进行训练
# 进行训练
kmeans = KMeans(n_clusters = 8,random_state=42).fit(X)

# 八个中心位置
# kmeans.cluster_centers_
  1. 把原始图像的像素数转化为特定的类别
# 通过标签找到对应的中心点,并且把数据还原成三维数据
segmented_img = kmeans.cluster_centers_[kmeans.labels_].reshape(533, 800, 3)
# 此时的图像当中只有八种不同的像素点
segmented_img
  1. 把原始数据分为不同的簇,以进行对比实验
segmented_imgs = []
n_colors = (10,8,6,4,2)
for n_clusters in n_colors:
    kmeans =  KMeans(n_clusters,random_state=42).fit(X)
    segmented_img = kmeans.cluster_centers_[kmeans.labels_]
    segmented_imgs.append(segmented_img.reshape(image.shape))
  1. 绘制图形
plt.figure(figsize = (10,5))
plt.subplot(231)
plt.imshow(image)
plt.title('Original image')

for idx,n_clusters in enumerate(n_colors):
    plt.subplot(232+idx)
    plt.imshow(segmented_imgs[idx])
    plt.title('{}colors'.format(n_clusters))
  1. 效果展示

    从图像来看,当簇的个数为2的时候,可以很好的把图像的前景和背景分割出来。
    在这里插入图片描述

3.10. 半监督学习

  1. 加载数据集并对数据集进行拆分

    首先,让我们将训练集聚类为50个集群,然后对于每个聚类,让我们找到最靠近质心的图像。 我们将这些图像称为代表性图像:

from sklearn.datasets import load_digits
# 加载并返回数字数据集(分类)
X_digits,y_digits = load_digits(return_X_y = True)

from sklearn.model_selection import train_test_split
# 将数组或矩阵切分为随机训练和测试子集
X_train,X_test,y_train,y_test = train_test_split(X_digits,y_digits,random_state=42)
  1. 进行训练
  • 第一类:直接选择50个样本进行逻辑回归的计算
# 使用逻辑回归进行半监督学习
from sklearn.linear_model import LogisticRegression
n_labeled = 50

log_reg = LogisticRegression(random_state=42)
log_reg.fit(X_train[:n_labeled], y_train[:n_labeled])
log_reg.score(X_test, y_test)

结果:0.8266666666666667

  • 第二类:用聚类算法找到距离簇中心最近的具有代表性的点,再进行逻辑回归的计算
# 对训练数据进行聚类
k = 50
kmeans = KMeans(n_clusters=k, random_state=42)
# 得到1347个样本到每个簇的距离
X_digits_dist = kmeans.fit_transform(X_train)

# 找簇中距离质心最近的点的索引
representative_digits_idx = np.argmin(X_digits_dist,axis=0)

# 把索引回传到训练样本中,找到当前的数据
X_representative_digits = X_train[representative_digits_idx]

现在让我们绘制这些代表性图像并手动标记它们:

# 画图并展示
plt.figure(figsize=(8, 2))
for index, X_representative_digit in enumerate(X_representative_digits):
    plt.subplot(k // 10, 10, index + 1)
    plt.imshow(X_representative_digit.reshape(8, 8), cmap="binary", interpolation="bilinear")
    plt.axis('off')

plt.show()

效果展示:
在这里插入图片描述

根据以上结果进行手动标记标签:

# 手动打标签
y_representative_digits = np.array([
    4, 8, 0, 6, 8, 3, 7, 7, 9, 2,
    5, 5, 8, 5, 2, 1, 2, 9, 6, 1,
    1, 6, 9, 0, 8, 3, 0, 7, 4, 1,
    6, 5, 2, 4, 1, 8, 6, 3, 9, 2,
    4, 2, 9, 4, 7, 6, 2, 3, 1, 1])

现在我们有一个只有50个标记实例的数据集,它们中的每一个都是其集群的代表性图像,而不是完全随机的实例,然后去训练:

log_reg = LogisticRegression(random_state=42)
log_reg.fit(X_representative_digits, y_representative_digits)
log_reg.score(X_test, y_test)

结果:0.92

  • 第三类:将标签传播到同一群集中的所有其他实例,然后进行逻辑回归的计算
# 先做一个空的标签
y_train_propagated = np.empty(len(X_train), dtype=np.int32)
# 遍历打标签
for i in range(k):
    y_train_propagated[kmeans.labels_==i] = y_representative_digits[i]
    
log_reg = LogisticRegression(random_state=42)
log_reg.fit(X_train, y_train_propagated)

log_reg.score(X_test, y_test)

结果:0.9288888888888889

  • 第四类:选择前20个来进行逻辑回归的计算
## 核心:簇 -> 索引 -> 样本
percentile_closest = 20

X_cluster_dist = X_digits_dist[np.arange(len(X_train)), kmeans.labels_]
for i in range(k):
    in_cluster = (kmeans.labels_ == i)
    # 选择属于当前簇的所有样本
    cluster_dist = X_cluster_dist[in_cluster] 
    # 排序找到前20个
    cutoff_distance = np.percentile(cluster_dist, percentile_closest) 
    # False True结果
    above_cutoff = (X_cluster_dist > cutoff_distance) 
    X_cluster_dist[in_cluster & above_cutoff] = -1
# 找到索引
partially_propagated = (X_cluster_dist != -1)
# 回传到样本
X_train_partially_propagated = X_train[partially_propagated]
y_train_partially_propagated = y_train_propagated[partially_propagated]
# 进行训练
log_reg = LogisticRegression(random_state=42)
log_reg.fit(X_train_partially_propagated, y_train_partially_propagated)
log_reg.score(X_test, y_test)

结果:0.9444444444444444

3.11. DBSCAN算法

  1. 准备数据集
from sklearn.datasets import make_moons
X, y = make_moons(n_samples=1000, noise=0.05, random_state=42)
  1. 导包并进行对比实验
from sklearn.cluster import DBSCAN
# eps:半径值,min_samples:一个点被视为核心点的邻域内的样本数

# 进行对比实验
dbscan = DBSCAN(eps = 0.05,min_samples=5)
dbscan.fit(X)

dbscan2 = DBSCAN(eps = 0.2,min_samples=5)
dbscan2.fit(X)
  1. 绘制图形
def plot_dbscan(dbscan, X, size, show_xlabels=True, show_ylabels=True):
    core_mask = np.zeros_like(dbscan.labels_, dtype=bool)
    core_mask[dbscan.core_sample_indices_] = True
    anomalies_mask = dbscan.labels_ == -1
    non_core_mask = ~(core_mask | anomalies_mask)

    cores = dbscan.components_
    anomalies = X[anomalies_mask]
    non_cores = X[non_core_mask]
    
    plt.scatter(cores[:, 0], cores[:, 1],
                c=dbscan.labels_[core_mask], marker='o', s=size, cmap="Paired")
    plt.scatter(cores[:, 0], cores[:, 1], marker='*', s=20, c=dbscan.labels_[core_mask])
    plt.scatter(anomalies[:, 0], anomalies[:, 1],
                c="r", marker="x", s=100)
    plt.scatter(non_cores[:, 0], non_cores[:, 1], c=dbscan.labels_[non_core_mask], marker=".")
    if show_xlabels:
        plt.xlabel("$x_1$", fontsize=14)
    else:
        plt.tick_params(labelbottom='off')
    if show_ylabels:
        plt.ylabel("$x_2$", fontsize=14, rotation=0)
    else:
        plt.tick_params(labelleft='off')
    plt.title("eps={:.2f}, min_samples={}".format(dbscan.eps, dbscan.min_samples), fontsize=14)
plt.figure(figsize=(18, 4))

plt.subplot(131)
plt.plot(X[:,0],X[:,1],'b.')
plt.xlabel("$x_1$", fontsize=14)
plt.ylabel("$x_2$", fontsize=14,rotation=0)
plt.title("Original image")

plt.subplot(132)
plot_dbscan(dbscan, X, size=100)

plt.subplot(133)
plot_dbscan(dbscan2, X, size=600, show_ylabels=True)

plt.show()
  1. 效果展示

    聚类算法中的DBSCAN算法效果展示如下图,此类算法有两个核心点,一个是半径大小,一个是领域点数量,下图在领域点个数相同的条件下,比较半径的大小。可以看出,当半径为0.05时,分为七类;当半径为0.2时,分为两类,对比原始数据图,两类正是我们需要的结果。
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/33191.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Flink 多流转换

多流转换分流使用侧输出流基本合流操作联合(Union)连接(Connect)基于时间的合流——双流联结(Join)窗口联结(Window Join)间隔联结(Interval Join)窗口同组联…

C#界面里Form.IsMdiContainer 属性的使用

C#界面里Form.IsMdiContainer 属性的使用 由于屏幕的局限,以及软件需求的复杂,并且还需要方便使用, 面对这样的任务,就需要好好地考虑使用多窗口的界面设计。 因为每一个窗口可以实现不同的功能,这样方便把相关的功能放在一起,不同的功能分为不同的窗口。 这样既可解决屏…

PC_DRAM

动态 RAM(DRAM)的刷新 刷新的过程实质上是先将原存信息读出,再由刷新放大器形成原信息并重新写入的再生过程 根据这个特点,可以估计刷新电路执行趟耗费的时间大致和访存时间相当 刷新放大器及读放大器均起此作用 由于存储单元被访问是随机的,有可能某些存储单元长期得不到访问…

OceanBase 4.0 all-in-one 版本如何离线升级 obd

今天遇到了一个问题,现象是这样的。 问题出现的原因: 在测试 ob 4.0 allinone 版本时,我用了自动部署的方式(autodeploy),发现部署完的集群无法启动,错误原因可以参考这里:https:/…

three.js之缓冲类型几何体顶点

文章目录简介构成代码顶点构成图形核心代码顶点的位置与颜色BufferAttribute颜色差值法向量不设置法向量顶点索引不复用顶点复用顶点专栏目录请点击 简介 顶点一般使我们在创建模型的时候使用的,他一般对应buffer类型的几何体,使用BufferGeometry创建 点…

有效备考浙大MEM的五个好习惯建议

作为去年上岸浙大mem项目的学长,很多身边计划备考的朋友都在咨询如何才能一年上岸,我在去年拿到了203分的成绩,在不影响工作和生活的前提下,自己认为有效备考浙大mem项目要基本做到五大好习惯,特别针对我们在职人群&am…

软件测试面试题及答案 这个可以免费白嫖的题库不要错过了

对于很多新手软件测试人来说,除了掌握扎实的专业技能之外,你还需要一份个互联网软件测试工程师面试题库才能在万千面试者中杀出重围,成功拿下offer。 一般软件测试的面试分为三轮:笔试,HR面试,技术面试。前…

2023最新SSM计算机毕业设计选题大全(附源码+LW)之java社区疫情防控管理系统nt4k1

最近发现近年来越来越多的人开始追求毕设题目的设创、和新颖性。以往的xx管理系统、xx校园系统都过时了。大多数人都不愿意做这类的系统了,确实,从有毕设开始就有人做了。但是很多人又不知道哪些毕设题目才算是新颖、创意。太老土的不想做,创…

HTML学生个人网站作业设计:宠物网站设计——宠物网站带会员登陆表单验证功能7页

⛵ 源码获取 文末联系 ✈ Web前端开发技术 描述 网页设计题材,DIVCSS 布局制作,HTMLCSS网页设计期末课程大作业 |宠物网页设计 | 保护动物网页 | 鲸鱼海豚主题 | 保护大象 | 等网站的设计与制作 | HTML宠物网页设计 | HTML期末大学生网页设计作业,Web大学…

怎么裁剪视频时长?建议收藏这些方法

我们经常会在业余的时间,观看一些视频来放松自己。小伙伴们平时有没有喜欢看的视频呢?有时视频中会出现一些比较精彩的片段,如果我们想要将这些精彩片段分享给好友,还需要跟他们说跳转到视频的哪个位置,在操作上有些麻…

量化交易进行回测时有哪些有意义的统计指标?

做量化少不了要做回测,因为回测做好了才能进行梯度研究分析,但是回测报中,需要包含哪些指标呢?下面分享一下,小编觉得还比较有意义的统计指标,以及参照分析的原则与意义。 策略收益率:这部份没得…

2022Q3母婴行业三大热门赛道总结

本篇我们将继续来分析22年Q3季度中母婴行业的高增长概念。 在母婴行业中,我们发现了3个高增长品类,分别是:果泥、辅食料理机、婴儿湿巾。 一、营养辅食类高增长概念——果泥 在婴幼儿阶段,除了母乳和婴幼儿奶粉之外,后…

[打卡笔记]-RK3399平台开发入门到精通系列视频-Linux 设备树

14天学习训练营导师课程: 内核笔记《RK3399平台开发入门到精通系列视频》 14天学习训练营导师课程:周贺贺《ARMv8/ARMv9架构-快速入门》 前言 学习了一下雪松老师的视频课程,然后做出本文笔记。 如果您也想baipiao,开通学习会员&…

计算机网络复习——第五章传输层

Today, ready to go home,啊哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈 《计算机网络》(谢希仁)内容总结 (javaguide.cn) 重点知识: Today, at home,啊哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈 进程(process&…

Python字符串及正则表达式

一: 字符串可以用单引号或双引号来创建,也可以用三引号来创建多行字符串。 String_1 加快发展 String_2 "促进生产" String_3 """吾家吾国, 吾家吾国, 吾家吾国, 吾家吾国。""…

JDBC在IDEA中配置mysql过程及编程详解

目录 jdbc编程简介 1.导入jar包 2.建立数据库连接 2.1 创建数据源,描述数据库服务器在哪 2.2 实现一个mysql客户端,通过网络和服务器进行通信 3.使用代码操作数据库 3.1 增删改操作 增加操作 更新操作 删除操作 3.2 查询操作 4.断开连接,释放资源 jdbc编程简介 J…

关联规则之 Apriori 算法实现

一、数据预览 Apriori 算法是电商数据挖掘中的经典算法,用于发现商品之间的关联规则,例如买了 A 和 B 的情况下是否还会买 C,通过计算商品组合之间的支持度和置信度来实现。首先我们来看一张订单表,包含订单编号,和商…

数据可视化之雷达图:自助数据集处理,完美演绎球员数据可视化

数据可视化,不只应用于工作或者财务报告,在某些场合通过使用图表展示数据,进行信息可视化表达,不仅可以省去繁冗的文字,还能更为清晰直观地展示,化平庸为神奇,让任何人有认真看的欲望。 当今世…

Thinkpad X201i笔记本电脑开机Fan Error

Thinkpad X201i笔记本电脑开机Fan Error1 背景2 现象3 更换风扇3.1 准备工具3.2 开始拆机1 背景 家里的老笔记本电脑,thinkpad X201i笔记本电脑,一直在使用,之前给风扇清过会,添加过硬盘,基本上也是拆了卸&#xff0c…

Logger.error还不知道怎么传参打印?看完这个你就明白了

Logger.error方法打印出堆栈信息,非常重要,可以使我们快速定位出相关问题,提高效率。 但是Logger.error有多个重载方法,不同的传参,打印结果各不一样。 下面,来看一个示例, 一、代码示例 impor…