聚类算法

聚类的概念:

     无监督问题:我们手里没有标签(数据集是未知类别标号的样本)

    聚类:相似的东西放到一组

   难点:如何评估,如何调参

k-means聚类算法

K-means 算法是一种最基本的基于距离划分的聚类算法,为十大数据挖掘算法之一。K-means 算法在对所给数据集进行聚类时,采用的是“非此即彼”的硬聚类方式。
K-means 算法使用时必须知道K 值的大小,即聚类的数目。难点找到合适的K值

自制k-means聚类算法

'''自制k-means聚类算法'''
import numpy as np
import pandas
import matplotlib.pyplot as plt
class means:
    def __init__(self,data,num_crowd_together):#data为数据集一般为样本数×特征数,num_crowd_together为k几簇
        self.data=data
        self.num_crowd_together=num_crowd_together
    def init_centres(self,data,num_crowd_together):#随机找出num_crowd_together个质心
        num_examples=data.shape[0]
        centres_ids=np.random.permutation(num_examples)#num_examples可以是数值,也可以是数组返回一个新的打乱后的数组,
         # 不改变原始数据,类似于“洗牌”,把一个序列的顺序完全打乱,这里num_examples是一个数组,作用生成生成 0 到 num_examples-1 的随机排列序列
        #np.random.shuffle(x):就地打乱,直接修改原数组
        centres_point=np.zeros((num_crowd_together,data.shape[1]))
        for i in range(num_crowd_together):#data[1, 3]和data[1][3]效果是一样的都是取第一行的第三列
            centres_id=centres_ids[i]
            centres_point[i]=data[centres_id,:]#取第centres_id 个样本的所有特征例如:
            # 若 data 是100张图片的特征(每张图片2048维特征),则 data[0, :] 就是第1张图片的2048维特征向量。
        return centres_point
    def close_centres_point(self,data,num_crowd_together,centres_point):
        '''分组'''
        num_examples=data.shape[0]
        examples_close_id=np.zeros((num_examples,1))
        for i in range(num_examples):
            distances=np.zeros((num_crowd_together,1))
            for j in range(num_crowd_together):
                distances[j]=np.sqrt(np.sum((data[i,:]-centres_point[j,:])**2))#计算样本点到每个质心的距离,欧式距离

            distance_id=np.argmin(distances)#argmin返回最小值的索引
            examples_close_id[i]=distance_id
        return examples_close_id
    def reassign_centroids(self,data,num_crowd_together,examples_close_id):#重新生成质心
        '''重新分配质心'''
        centres_point = np.zeros((num_crowd_together, data.shape[1]))
        for i in range(num_crowd_together):
            '''当 data 是二维数组(样本矩阵)时:整数索引:data[0, :] → 取第0行(单个样本)。
布尔索引:data[boolean_array, :] → 取所有 boolean_array 中为 True 的行(批量样本)'''
            closest_ids = examples_close_id==i#作用:生成一个布尔数组,closest_ids 是 (num_examples, 1) 的布尔矩阵
            centres_point[i]=np.mean(data[closest_ids.flatten(),:],axis=0)
        return centres_point

if __name__=="__main__":
    data=pandas.read_csv(r'D:\kuake_download\数据挖掘经典算法\iris.csv')
    num_example=data.shape[0]
    num_crowd_together=4
    x_train_data=data[['volatile acidity','citric acid']].values.reshape((num_example,2))
    # pands格式的数据data[['volatile acidity','citric acid']]表示取出'volatile acidity','citric acid'这两列的数据,
    mean=means(x_train_data,num_crowd_together)

    centres_point=mean.init_centres(data=x_train_data,num_crowd_together=num_crowd_together)#分为2簇,随机取出2个质心
    for i in range(10): #循环5次
       examples_close_id= mean.close_centres_point(data=x_train_data,num_crowd_together=num_crowd_together,centres_point=centres_point)#分组
       centres_point=mean.reassign_centroids(x_train_data,num_crowd_together,examples_close_id)#重新分配质心
    #可视化
    plt.figure(figsize=(12,5))
    for i in range(num_crowd_together):
        closest_ids = examples_close_id==i#作用:生成一个布尔数组,closest_ids 是 (num_examples, 1) 的布尔矩阵
        closest_ids=closest_ids.flatten()
        #loc[行掩码, 列名]明确表示「筛选行(current_examples_index)→ 取列(x_axis)」
        plt.scatter(data.loc[closest_ids,'volatile acidity'],data.loc[closest_ids,'citric acid'],label=i)
    for j in range(num_crowd_together):
        plt.scatter(centres_point[j,0],centres_point[j,1],c='black',marker='x',)
    plt.show()

调用官方现有的k-means算法

更多k-means的用法看https://scikit-learn.org/stable/modules/generated/sklearn.cluster.KMeans.html#sklearn.cluster.KMeans

from sklearn.cluster import KMeans
kmeans = KMeans(n_clusters = k,n_init='auto',max_iter = iteration) 
'''Kmeans常用的一些参数,n_clusters:分为几个簇;max_iter:单次运行的 k 均值算法的最大迭代次数(循环几次);random_state:确定质心初始化的随机数生成,使随机具有确定性类似seed()'''
kmeans.fit_predict(data) #data为数据集一般为样本数×特征数;开始聚类,返回值:每个样本所属聚类的索引

如何找到合适的K值

from sklearn. metrics import silhouette_score
score=silhouette_score(data,kmeans.labels_)#kmeans.labels_每个点的标签;score:float类型,越接近1说明k值越合适

使用k-means对图像进行分割小玩法

from sklearn.cluster import KMeans
import cv2
import matplotlib.pyplot as plot

image=plot.imread(r'2.png')
plot.figure(figsize=(20,20))
plot.subplot(2,3,1)
plot.imshow(image)
image_data=image.reshape(-1,3)

j=1
for i in range(2,11,2):
    j+=1
    kmeans=KMeans(i,random_state=42)
    kmeans.fit_predict(image_data)
    print(kmeans.cluster_centers_)
    colors=kmeans.cluster_centers_[kmeans.labels_].reshape(image.shape)


    plot.subplot(2,3,j)
    plot.imshow(colors)
    plot.title(f'{i} colors')
plot.show()

DBSCAN聚类算法(效果更好)

用法跟k-means聚类算法类似

from sklearn.cluster import DBSCAN
dbscan=DBSCAN(eps=0.5,min_samples=4)#初始化对象,指定半径为0.5,每个半径圆至少包含四个样本
dbscan.fit_predict(x_train)#data是数据集 样本数×特征数
dbscan.labels_#每个样本属于那个簇,这里的labels比k-means多了一个-1索引用来表示,离群点即噪音样本

更多DBSCAN的用法看https://scikit-learn.org/stable/modules/generated/sklearn.cluster.DBSCAN.html#sklearn.cluster.DBSCAN

降维算法

主成分分析 (PCA) 

主成分分析 (PCA) 的原理

主成分分析是一种常用的降维技术,其核心目标是通过线性变换将数据投影到低维度空间中,同时尽可能保留原始数据中的方差信息。

代码实现

在scikit-learn中,与PCA相关的类都在sklearn.decomposition包中。最常用的PCA类就是sklearn.decomposition.PCA

除了PCA类以外,最常用的PCA相关类还有KernelPCA类,在上面我们也讲到了,它主要用于非线性数据的降维,需要用到核技巧。因此在使用的时候需要选择合适的核函数并对核函数的参数进行调参。

另外一个常用的PCA相关类是IncrementalPCA类,它主要是为了解决单机内存限制的。有时候我们的样本量可能是上百万+,维度可能也是上千,直接去拟合数据可能会让内存爆掉, 此时我们可以用IncrementalPCA类来解决这个问题。IncrementalPCA先将数据分成多个batch,然后对每个batch依次递增调用partial_fit函数,这样一步步的得到最终的样本最优降维。

from sklearn.decomposition import PCA
pca=PCA(n_components=0.9)#n_components:保留百分之多少的方差信息,这里保存了90%的方差信息
data_pca=pca.fit_transform(data)#进行降维,data原数据集,类型:样本数×特征数;返回值data_pca降维后得到的低维度数据集
#KernelPCA,IncrementalPCA的用法都是类似的

UMAP降维算法

UMAP(Uniform Manifold Approximation and Projection)是一种先进的非线性降维技术,用于将高维数据集转换为低维空间中的表示,同时尽可能保留原始数据的复杂结构和拓扑特性(样本间的关系)。它特别适用于可视化分析和机器学习领域的预处理步骤。

为什么使用 UMAP?
在数据分析、机器学习和深度学习任务中,数据通常是 高维的(如 100 维、1000 维),直接分析或可视化较困难。UMAP 可以将高维数据降维至 2D/3D,便于可视化和理解数据结构。

UMAP 主要用于:

数据可视化(将高维数据映射到 2D 或 3D)
降维(减少特征维度,加速机器学习)
聚类前处理(降维后进行 K-Means 等聚类)
异常检测(降维后分析数据分布)

代码实现

from umap import UMAP
# UMAP 降维到 2D
umap_2d = UMAP(n_components=2, random_state=42)
data_umap = umap_2d.fit_transform(data)#降维,data类型:样本数×特征数

分类/回归算法

决策树(decision tree):决策树是一种树形结构监督学习算法,广泛应用于分类任务和回归任务中。它通过递归地将数据集分割成更小的子集,最终形成一个树形模型,用于预测新数据的输出。

代码实现

import pandas as pd
from sklearn.tree import DecisionTreeClassifier, export_text#决策树分类; export_text用来把训练好的决策树(clf)以 文本规则 的形式导出
from sklearn.tree import DecisionTreeRegressor#决策树回归
# 加载数据
data = pd.read_csv('data.csv')
X = data.drop('target', axis=1)
y = data['target']
# 构建决策树模型
clf = DecisionTreeClassifier()
clf.fit(X_train, y_train)#X_train:输入特征, y_train:标签
# 预测
y_pred = clf.predict(X_test)
# 输出决策树结构
tree_rules = export_text(clf, feature_names=list(X.columns))
print(tree_rules)

DecisionTreeClassifier DecisionTreeRegressor的一些常用参数

随机森林算法

随机森林是一种基于集成学习(Ensemble Learning)的机器学习算法,属于 Bagging 类型的集成方法。它通过构建多个决策树(Decision Tree)并将它们的预测结果进行集成,从而提高模型的准确性和鲁棒性。随机森林广泛应用于分类、回归以及特征选择等任务。

核心思想

  • 通过构建多棵决策树,每棵树独立地对数据进行预测。
  • 最终的预测结果是所有树的预测结果的综合(分类任务使用投票,回归任务使用平均)。

随机森林的构建过程
Bootstrap 采样:
从训练集中随机抽取样本(有放回),生成多个子数据集。

构建决策树(训练):
对每个子数据集,构建一棵决策树。
在树的每个节点分裂时,随机选择一部分特征进行分裂。

集成预测:
对于分类任务,采用 多数投票 的方式确定最终结果。
对于回归任务,采用 平均值 作为最终结果。

from sklearn.ensemble import RandomForestClassifier#随机森林分类
from sklearn.ensemble import RandomForestRegressor#随机森林回归
randomforest=RandomForestRegressor(n_estimators=100)#n_estimators构建多少棵决策树,这里指构建100棵,其他的常用参数跟决策树一样
randomforest=randomforest.fit(x_f,x_t)#x_f输入特征,x_t输入标签;构建随机森林模型
randomforest.predict(x)#预测;x:输入数据

SVM(支持向量机)

支持向量机(support vector machines,SVM)是一种二分类模型,它将实例的特征向量映射为空间中的一些点,SVM 的目的就是想要画出一条线,以 “最好地” 区分这两类点,以至如果以后有了新的点,这条线也能做出很好的分类。SVM 适合中小型数据样本、非线性、高维的分类问题。

1.1 SVM 基本概念

将实例的特征向量(以二维为例)映射为空间中的一些点,如下图的实心点和空心点,它们属于不同的两类。SVM 的目的就是想要画出一条线,以“最好地”区分这两类点,以至如果以后有了新的点,这条线也能做出很好的分类。每条线都可以叫做一个划分超平面。

为什么要叫作“超平面”呢?
答:因为样本的特征很可能是高维的,此时样本空间的划分就不是一条线了。

画线的标准是什么?/ 什么才叫这条线的效果好?/ 哪里好?
答:SVM 将会寻找可以区分两个类别并且能使间隔(margin)最大的划分超平面。比较好的划分超平面,样本局部扰动时对它的影响最小、产生的分类结果最鲁棒、对未见示例的泛化能力最强。

为什么要让 margin 尽量大?
答:因为大 margin 犯错的几率比较小,也就是更鲁棒啦。

支持向量是什么?
答:从上图可以看出,虚线上的点到划分超平面的距离都是一样的,实际上只有这几个点共同确定了超平面的位置,因此被称作 “支持向量(support vectors)”,“支持向量机” 也是由此来的。

代码分析

svm有一些类

kernel参数的作用可以理解为在现有数据集的维度下无法画出超平面,利用kernel将数据集的维度从低维升到高维,在这个高维空间上进行画出超平面,同时在之后的预测过程中也要将数据集升到相同的高维上进行预测

from sklearn import svm
svc=svm.SVC()#以svc分类器为例,初始化分类器
svc.fit(data,target)#训练分类器模型;data数据集类型:样本数×特征数;target:数据集标签
svc.predict(t_data)#预测;t_data数据集类型:样本数×特征数

KNN算法

KNN 算法,或者称 k最邻近算法,是 有监督学习 中的 分类算法 。它可以用于分类或回归问题,但它通常用作分类算法

KNN核心思想


        KNN 的全称是 K Nearest Neighbors,意思是 K 个最近的邻居。该算法用 K 个最近邻来干什么呢?其实,KNN 的原理就是:当预测一个新样本的类别时,根据它距离最近的 K 个样本点是什么类别来判断该新样本属于哪个类别(多数投票)。

主要有两个,K值的选取点距离的计算(通常用欧式距离,曼哈顿距离)

K值选择
通过交叉验证(将样本数据按照一定比例,拆分出训练用的数据和验证用的数据,比如6:4拆分出部分训练数据和验证数据),从选取一个较小的K值开始,不断增加K的值,然后计算验证集合的方差或准确率,最终找到一个比较合适的K值。

代码分析

from sklearn.neighbors import KNeighborsClassifier
knn=KNeighborsClassifier()#初始化KNN分类对象;常用的参数n_neighbors:在进行预测时,需要参考的“邻居”数量。也就是公式里的 k 值默认为5
#weights :决定邻居的投票如何影响最终结果。p:定义计算距离的公式(欧式距离/曼哈顿距离)
knn.fit(data,target)#训练knn模型;data:数据集类型样本数×特征数;target:数据集样本标签
knn.predict(t_data)#预测,t_data:数据集类型:样本数×特征数
Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐