9. 聚类算法实验分析
聚类算法实践
- Kmeans与Dbscan算法
- 半监督问题解决方案
- 聚类评估方法
环境:
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)
Kmeans
# 导入所需库
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])
# 生成样本数据集
X, y = make_blobs(n_samples=2000, centers=blob_centers, cluster_std=blob_std, random_state=7)
# 定义绘制数据集的函数
def plot_clusters(X, y=None):
plt.scatter(X[:, 0], X[:, 1], c=y, s=1) # 绘制散点图
plt.xlabel("$x_1$", fontsize=14) # 设置x轴标签
plt.ylabel("$x_2$", fontsize=14, rotation=0) # 设置y轴标签,rotation=0表示标签水平显示
# 创建一个图形窗口
plt.figure(figsize=(8, 4))
# 调用绘制数据集的函数
plot_clusters(X)
# 显示图形
plt.show()
决策边界
# jupyter notebook
from sklearn.cluster import KMeans
k = 5
kmeans = KMeans(n_clusters = k,random_state=42)
y_pred = kmeans.fit_predict(X)
y_pred
kmeans.labels_
kmeans.cluster_centers_
# fit_predict(X)与kmeans.labels_ 得到预测结果是一致的,y_pred与kmeans.labels_ 值相等
X_new = np.array([[0,2],[3,2],[-3,3],[-3,2.5]])
kmeans.predict(X_new)
kmeans.transform(X_new) #可用transform得到每个样本到各个簇中心的距离
9.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=50,
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) # 设置x轴标签
else:
plt.tick_params(labelbottom='off') # 不显示x轴标签
if show_ylabels:
plt.ylabel("$x_2$", fontsize=14, rotation=0) # 设置y轴标签
else:
plt.tick_params(labelleft='off') # 不显示y轴标签
plt.figure(figsize=(8, 4))
plot_decision_boundaries(kmeans, X) # 绘制决策边界
plt.show() # 显示图形
9.2-建模流程解读
kmeans_iter1 = KMeans(n_clusters = 5,init = 'random',n_init = 1,max_iter=1,random_state=1)
kmeans_iter2 = KMeans(n_clusters = 5,init = 'random',n_init = 1,max_iter=2,random_state=1)
kmeans_iter3 = KMeans(n_clusters = 5,init = 'random',n_init = 1,max_iter=3,random_state=1)
kmeans_iter1.fit(X)
kmeans_iter2.fit(X)
kmeans_iter3.fit(X)
plt.figure(figsize=(12,8))
plt.subplot(321)
plot_data(X)
plot_centroids(kmeans_iter1.cluster_centers_, circle_color='r', cross_color='k')
plt.title('Update cluster_centers')
plt.subplot(322)
plot_decision_boundaries(kmeans_iter1, X,show_xlabels=False, show_ylabels=False)
plt.title('Label')
plt.subplot(323)
plot_decision_boundaries(kmeans_iter1, X,show_xlabels=False, show_ylabels=False)
plot_centroids(kmeans_iter2.cluster_centers_,)
plt.subplot(324)
plot_decision_boundaries(kmeans_iter2, X,show_xlabels=False, show_ylabels=False)
plt.subplot(325)
plot_decision_boundaries(kmeans_iter2, X,show_xlabels=False, show_ylabels=False)
plot_centroids(kmeans_iter3.cluster_centers_,)
plt.subplot(326)
plot_decision_boundaries(kmeans_iter3, X,show_xlabels=False, show_ylabels=False)
plt.show()
以上的代码演示了K均值聚类算法的基本流程,包括对不同迭代次数的效果进行可视化比较。以下是算法流程的简要概述:
-
数据准备:
- 生成了一个模拟数据集
X
,其中包括多个数据点。
- 生成了一个模拟数据集
-
创建K均值模型实例:
- 创建了三个不同迭代次数的K均值模型实例
kmeans_iter1
、kmeans_iter2
和kmeans_iter3
。
- 创建了三个不同迭代次数的K均值模型实例
-
拟合模型:
- 使用不同的K均值模型对数据集
X
进行拟合,通过不同的迭代次数来演示模型在不同迭代阶段的效果。
- 使用不同的K均值模型对数据集
-
可视化:
- 创建一个图形窗口,包含六个子图,用于可视化不同迭代次数下的效果。
- 在每个子图中,使用
plot_data
函数绘制数据点,使用plot_centroids
函数绘制聚类中心,使用plot_decision_boundaries
函数绘制决策边界。 - 在子图中,标题指明了当前展示的内容,如 "Update cluster_centers" 表示展示聚类中心的更新,"Label" 表示展示聚类结果。
-
显示图形:
- 调用
plt.show()
来显示包含多个子图的图形窗口,以便比较不同迭代次数下的K均值聚类效果。
- 调用
总的来说,该代码演示了K均值聚类算法的迭代过程,通过逐步调整聚类中心来逼近数据的簇结构,并可视化不同迭代次数下的聚类结果,帮助理解K均值聚类的工作原理。
9.3-不稳定结果
# 定义一个函数,用于比较两个不同K均值聚类器的效果
def plot_clusterer_comparison(c1, c2, X):
c1.fit(X) # 使用第一个聚类器拟合数据
c2.fit(X) # 使用第二个聚类器拟合数据
# 创建一个图形窗口,包含两个子图,用于比较两个聚类器的决策边界
plt.figure(figsize=(12, 4))
# 在子图 1 中绘制第一个聚类器的决策边界
plt.subplot(121)
plot_decision_boundaries(c1, X)
# 在子图 2 中绘制第二个聚类器的决策边界
plt.subplot(122)
plot_decision_boundaries(c2, X)
# 创建两个不同的K均值聚类器实例
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)
# 调用比较聚类器效果的函数,传入两个不同的聚类器和数据集X
plot_clusterer_comparison(c1, c2, X)
在K均值聚类中,结果的稳定性取决于初始聚类中心的选择和算法的随机性。以下是关于K均值聚类不稳定结果的简要概述:
-
初始聚类中心的随机性:
- K均值聚类依赖于初始聚类中心的选择。不同的初始中心点可能会导致不同的聚类结果。
- 在上述代码中,使用
init='random'
参数来随机初始化聚类中心,不同的随机种子(random_state
)可能会导致不同的初始中心点,进而影响最终的聚类结果。
-
算法的随机性:
- K均值聚类算法的迭代过程涉及到计算样本点与聚类中心的距离,并根据距离来更新样本点的归属。这个过程在每次迭代中都会引入一定的随机性。
- 不同的初始中心点和随机性可能导致不同的迭代轨迹,最终收敛到不同的聚类结果。
-
多次运行和结果比较:
- 为了解决K均值聚类的不稳定性,通常需要多次运行算法,每次使用不同的随机种子或不同的初始中心点。
- 然后,可以比较多次运行的结果,选择最合适的聚类结果,例如通过评估聚类质量的指标(如轮廓系数)来选择最佳的结果。
总之,K均值聚类在某些情况下可能产生不稳定的结果,这是由于其初始聚类中心的随机性和算法的随机性所导致的。为了得到可靠的聚类结果,通常需要进行多次运行和结果比较,以选择最优的聚类解决方案。
9.4-评估指标-Inertia
Inertia(内部距离平方和)是K均值聚类中常用的一种评估指标,用于衡量聚类结果的紧密度。以下是对Inertia的简要概述:
-
Inertia的计算:
- Inertia是每个样本点与其所属簇的质心之间距离的平方和。具体地,对于每个样本,计算其与所属簇的质心的欧氏距离,然后将这些距离的平方值相加,得到Inertia值。
- 公式表示为:Inertia = Σ(每个样本到所属簇质心的距离^2)
-
Inertia的含义:
- Inertia越小越好,表示样本点与其所属簇的质心越接近,簇内的紧密度越高。
- Inertia值的大小反映了聚类的紧密度,值越小说明聚类效果越好,簇内的样本点越接近。
-
评估聚类结果:
- 通常情况下,选择Inertia最小的聚类结果作为最优的聚类解决方案。较小的Inertia值意味着更紧密的聚类。
- 但要注意,Inertia倾向于随着簇的数量增加而减小,因此在选择簇的数量时需要综合考虑Inertia和其他指标,如轮廓系数等。
在提供的代码示例中,通过 kmeans.inertia
可以获取K均值聚类模型的Inertia值,用于评估当前的聚类效果。较低的Inertia值表示更好的聚类结果。
9.5-如何找到合适的K值
# 创建K均值聚类模型列表,分别尝试从1到9个簇
kmeans_per_k = [KMeans(n_clusters=k).fit(X) for k in range(1, 10)]
# 计算每个模型的Inertia值
inertias = [model.inertia_ for model in kmeans_per_k]
# 创建一个图形窗口
plt.figure(figsize=(8, 4))
# 绘制Inertia值随簇数目变化的折线图
plt.plot(range(1, 10), inertias, 'bo-') # 'bo-'表示蓝色圆点连线
plt.axis([1, 8.5, 0, 1300]) # 设置坐标轴范围
plt.show() # 显示图形
以上代码演示了如何通过绘制Inertia值随簇数量变化的图表来帮助选择合适的K值,以下是简要概述:
-
尝试多个K值:
- 通过循环从1到某个最大值(此处为9),创建多个K均值聚类模型,每个模型尝试一个不同的簇数量。
-
计算Inertia值:
- 对于每个K值,使用K均值模型拟合数据并计算其Inertia值,Inertia值衡量了簇内样本点与其所属簇质心的距离平方和。
-
绘制Inertia值图表:
- 将不同K值对应的Inertia值绘制成折线图。横坐标是K值,纵坐标是Inertia值。
- 折线图通常会呈现出一个所谓的“肘部(Elbow)”点,这是Inertia值迅速下降并趋于平稳的点。
-
选择肘部点:
- 通过观察Inertia值随K值变化的图表,找到一个肘部点,该点通常是Inertia值开始趋于平稳的位置。
- 肘部点通常表示了数据的真正聚类结构,因此可以选择对应的K值作为最优的簇数量。
-
注意调整范围:
- 图表的横坐标范围可能需要根据具体问题进行调整,以便更清晰地观察肘部点。
- 同时,选择K值时还需结合领域知识和问题背景来综合考虑。
总之,通过绘制Inertia值随K值变化的图表并找到肘部点,可以帮助选择合适的K值,从而获得最佳的K均值聚类结果。
9.6-轮廓系数的作用
轮廓系数
- : 计算样本i到同簇其他样本的平均距离 。 越小,说明样本i越应该被聚类到该簇。将 称为样本i的簇内不相似度。
- 计算样本i到其他某簇 的所有样本的平均距离 ,称为样本i与簇 的不相似度。定义为样本i的簇间不相似度: = min {bi1, bi2, ..., bik}
结论:
-
si接近1,则说明样本i聚类合理;
-
si接近-1,则说明样本i更应该分类到另外的簇;
-
若si 近似为0,则说明样本i在两个簇的边界上。
# 导入Silhouette评分指标
from sklearn.metrics import silhouette_score
# 计算当前K均值模型的Silhouette评分
silhouette_score(X, kmeans.labels_)
# 获取K均值模型列表
kmeans_per_k
# 计算不同K值下的Silhouette评分
silhouette_scores = [silhouette_score(X, model.labels_) for model in kmeans_per_k[1:]]
# 创建一个图形窗口
plt.figure(figsize=(8, 4))
# 绘制Silhouette评分随簇数目变化的折线图
plt.plot(range(2, 10), silhouette_scores, 'bo-') # 'bo-'表示蓝色圆点连线
plt.show() # 显示图形
轮廓系数(Silhouette Score)是一种用于评估聚类结果质量的指标,其作用可以简要概述如下:
-
度量簇内紧密度和簇间分离度:
- 轮廓系数同时考虑了簇内样本点之间的距离(紧密度)和不同簇之间的距离(分离度)。
- 通过比较样本点与其所属簇内的平均距离和与最近非所属簇的平均距离,轮廓系数度量了聚类的紧密性和分离性。
-
取值范围和解释:
- 轮廓系数的取值范围在-1到1之间。
- 接近1表示样本点很好地属于其所在簇,簇内紧密度高,簇间分离度明显。
- 接近0表示样本点位于簇边界附近,簇内外的距离相似。
- 接近-1表示样本点更可能属于其他簇,簇内紧密度低,簇外距离更近。
-
作为聚类质量的度量标准:
- 轮廓系数是一种常用的聚类质量度量标准,用于衡量聚类结果的优劣。
- 较高的轮廓系数通常表示较好的聚类结果,簇内样本点更加紧密,并且不同簇之间更加分离。
-
选择最佳簇数量:
- 轮廓系数可以帮助选择最佳的簇数量(K值)。通过计算不同K值下的轮廓系数,可以选择具有最高轮廓系数的K值作为最优的簇数量。
- 最佳的K值通常对应于轮廓系数最大的情况,这表示在该K值下聚类效果最佳。
总之,轮廓系数是一种有用的聚类评估指标,可以帮助衡量聚类结果的紧密度和分离度,以及选择最佳的簇数量。通过轮廓系数,可以更好地理解和选择适合数据的聚类解决方案。
9.7-Kmenas算法存在的问题
# 导入所需库
from sklearn.datasets import make_blobs
import numpy as np
import matplotlib.pyplot as plt
# 生成数据集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]]))
# 生成数据集2
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)
# 创建"好"的K均值模型,指定初始聚类中心
kmeans_good = KMeans(n_clusters=3, init=np.array([[-1.5, 2.5], [0.5, 0], [4, 0]]), n_init=1, random_state=42)
# 创建"坏"的K均值模型,随机初始化聚类中心
kmeans_bad = KMeans(n_clusters=3, random_state=42)
# 拟合数据
kmeans_good.fit(X)
kmeans_bad.fit(X)
# 创建图形窗口
plt.figure(figsize=(10, 4))
# 绘制"好"的K均值模型决策边界
plt.subplot(121)
plot_decision_boundaries(kmeans_good, X)
plt.title('Good - inertia = {}'.format(kmeans_good.inertia_))
# 绘制"坏"的K均值模型决策边界
plt.subplot(122)
plot_decision_boundaries(kmeans_bad, X)
plt.title('Bad - inertia = {}'.format(kmeans_bad.inertia_))
以上代码演示了K均值算法的一个重要问题,即对于不同的初始聚类中心的选择,K均值算法可能会得到不同的聚类结果,这一问题可以通过Inertia值来说明。以下是简要概述K均值算法存在的问题:
-
初始聚类中心的选择问题:
- K均值算法的聚类结果高度依赖于初始聚类中心的选择。
- 不同的初始聚类中心可能导致完全不同的最终聚类结果。
-
Inertia值不一定准确:
- Inertia值通常用于评估聚类结果的质量,较小的Inertia值表示较好的聚类。
- 但Inertia值不一定总能反映出聚类结果的质量,因为它受初始聚类中心的影响。
- 在某些情况下,即使Inertia值较小,实际的聚类结果可能不够准确。
-
解决方法:
- 为了克服K均值算法对初始聚类中心的敏感性,可以采用多次运行算法并选择具有最小Inertia值的模型,但这仍然不是绝对准确的解决方案。
- 另一种方法是使用更稳定的聚类算法,如层次聚类(Hierarchical Clustering)或谱聚类(Spectral Clustering),它们不像K均值那样受初始值的影响。
总之,K均值算法存在对初始聚类中心选择敏感的问题,导致不同的初始化可能会产生不同的聚类结果,这需要谨慎处理。因此,在使用K均值算法时,需要考虑多次运行并结合其他评估指标来评估聚类结果的稳定性和准确性。
9.8-应用实例-图像分割
# jupyter notebook
# 导入所需库
from matplotlib.image import imread
import matplotlib.pyplot as plt
# 读取图像数据
image = imread('ladybug.png')
# 输出图像数据的形状
image.shape
# 重塑图像数据以便进行聚类
X = image.reshape(-1, 3)
X.shape
# 使用K均值算法进行图像聚类,分为8个簇
kmeans = KMeans(n_clusters=8, random_state=42).fit(X)
# 获取簇中心点
kmeans.cluster_centers_
# 根据聚类结果重构分割后的图像
segmented_img = kmeans.cluster_centers_[kmeans.labels_].reshape(533, 800, 3)
# 初始化一组不同簇数的分割图像
segmented_imgs = []
n_colors = (10, 8, 6, 4, 2)
# 对每个不同簇数进行图像分割
for n_cluster in n_colors:
kmeans = KMeans(n_clusters=n_cluster, random_state=42).fit(X)
segmented_img = kmeans.cluster_centers_[kmeans.labels_]
segmented_imgs.append(segmented_img.reshape(image.shape))
# 创建图形窗口
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))
以上代码演示了K均值算法在图像分割领域的应用实例。以下是简要概述K均值算法的应用实例 - 图像分割:
-
图像分割:
- 图像分割是计算机视觉领域的重要任务之一,旨在将一张图像分成若干个具有相似特征的区域或簇。
- 图像分割可以用于对象检测、图像处理、医学图像分析等各种应用。
-
K均值算法在图像分割中的应用:
- K均值算法被用于将图像中的像素分成不同的颜色簇,从而实现图像分割。
- 代码中首先将图像的像素数据重塑成一个二维数组,每一行代表一个像素点的颜色信息(通常是RGB值)。
- 然后,通过K均值算法对像素点进行聚类,根据颜色相似性将像素点分为不同的簇。
- 最终,使用每个簇的聚类中心来重构图像,得到分割后的图像。
-
不同簇数的影响:
- 代码中演示了不同簇数对图像分割结果的影响。通过调整簇数(
n_colors
),可以得到不同颜色数量的分割图像。 - 更多的簇数通常意味着更细粒度的分割,而较少的簇数则可能导致颜色较多的区域被合并。
- 代码中演示了不同簇数对图像分割结果的影响。通过调整簇数(
-
实际应用:
- 图像分割在计算机视觉中具有广泛的应用,如物体检测、图像分析、背景去除、医学图像分析等。
- K均值算法是图像分割中的一种简单而有效的方法,但也有一些局限性,如对初始聚类中心的敏感性。
总之,K均值算法在图像分割中的应用示例演示了如何使用聚类方法将图像像素划分成不同的簇,以实现图像的分割和处理。这是计算机视觉中的一个重要任务,可以帮助解决各种图像分析和处理问题。
9.9-半监督学习
半监督学习
首先,让我们将训练集聚类为50个集群, 然后对于每个聚类,让我们找到最靠近质心的图像。 我们将这些图像称为代表性图像:
# jupyter notebook
from sklearn.datasets import load_digits
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
import matplotlib.pyplot as plt
import numpy as np
# 加载手写数字数据集
X_digits, y_digits = load_digits(return_X_y=True)
# 将数据集划分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X_digits, y_digits, random_state=42)
# 使用逻辑回归模型进行初始训练
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个簇
k = 50
kmeans = KMeans(n_clusters=k, random_state=42)
X_digits_dist = kmeans.fit_transform(X_train)
X_digits_dist.shape # (1347, 50)
# 选取代表性的样本
representative_digits_idx = np.argmin(X_digits_dist, axis=0)
representative_digits_idx.shape # (50,)
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])
# 使用逻辑回归模型对代表性样本进行训练
log_reg = LogisticRegression(random_state=42)
log_reg.fit(X_representative_digits, y_representative_digits)
log_reg.score(X_test, y_test)
# 准确率:0.9244444444444444
# 将标签传播到同一群集中的所有其他实例
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]
cutoff_distance = np.percentile(cluster_dist, percentile_closest)
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.9422222222222222
以上代码演示了半监督学习的应用示例,特别是在手写数字分类任务中。以下是半监督学习的用法和意义的简要概述:
-
半监督学习的用法:
- 半监督学习是一种机器学习范式,结合了有标签数据和无标签数据,以提高模型的性能。
- 在半监督学习中,通常只有一小部分数据标记有真实标签,而大多数数据没有标签。
- 半监督学习的目标是利用有标签数据的信息来提高对未标签数据的预测,以提高模型的泛化能力。
-
示例中的应用:
- 代码中的示例使用了半监督学习来改进手写数字分类任务的性能。
- 初始阶段,仅使用了很少数量的有标签数据(50个样本)来训练一个逻辑回归分类器,得到较低的准确率(0.826)。
- 接下来,使用K均值聚类算法对训练集进行聚类,将训练集分成50个簇,并选择每个簇的代表性样本。
- 为代表性样本手动标记真实标签,然后使用这些标记样本来训练逻辑回归模型,提高了准确率(0.924)。
- 进一步,将标签传播到每个簇中的所有其他实例,以提供更多的有标签数据。
- 最后,使用这些有标签数据进行训练,得到更高的准确率(0.928)。
-
半监督学习的意义:
- 半监督学习充分利用了未标签数据,通过将其结合到模型中,提高了模型性能。
- 在许多实际应用中,获取大量有标签数据可能是昂贵和耗时的,但有大量未标签数据。
- 半监督学习允许我们更充分地利用现有数据,提高模型的性能,同时降低了数据标记的成本。
- 在特别困难的分类问题中,半监督学习可以是一种有效的策略,因为它可以提供更多的信息以改进分类器。
总之,半监督学习是一种有用的机器学习方法,可以在有限的有标签数据下提高模型性能,并应用于各种领域,以更好地利用未标签数据和降低数据标记的成本。
9.10-DBSCAN算法
# 导入所需库
from sklearn.datasets import make_moons
import matplotlib.pyplot as plt
import numpy as np
from sklearn.cluster import DBSCAN
# 生成合成数据集
X, y = make_moons(n_samples=1000, noise=0.05, random_state=42)
# 绘制数据集的散点图
plt.plot(X[:,0],X[:,1],'b.')
# 使用DBSCAN算法进行聚类
dbscan = DBSCAN(eps=0.05, min_samples=5)
dbscan.fit(X)
# 输出前10个样本的聚类标签
dbscan.labels_[:10]
# 获取核心样本的索引
dbscan.core_sample_indices_[:10]
# 获取所有不同的聚类标签
np.unique(dbscan.labels_)
# 使用不同的eps值再次运行DBSCAN
dbscan2 = DBSCAN(eps=0.2, min_samples=5)
dbscan2.fit(X)
# 定义绘制DBSCAN结果的函数
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)
# 绘制DBSCAN的聚类结果
plt.figure(figsize=(9, 3.2))
plt.subplot(121)
plot_dbscan(dbscan, X, size=100)
plt.subplot(122)
plot_dbscan(dbscan2, X, size=600, show_ylabels=False)
plt.show()
DBSCAN(Density-Based Spatial Clustering of Applications with Noise)是一种密度聚类算法,其用法和作用可以简要概括如下:
-
用途:
- DBSCAN主要用于聚类分析,尤其适用于具有不规则形状和不同密度簇的数据集。
- 可以用于异常检测,将异常点标记为噪声点。
-
工作原理:
- DBSCAN基于密度的聚类方法,通过考察样本点周围的密度来判断它们是否属于同一簇。
- 核心思想是:一个核心点周围至少包含一定数量(由
min_samples
参数决定)的邻居样本点,才会形成一个簇。
-
参数说明:
eps
:用于定义邻域的半径,表示一个样本点到其邻居点的最大距离。min_samples
:定义核心点所需的最小邻居样本数。- 可选参数还包括距离度量方式等。
-
优点:
- 可以自动发现不同形状和大小的簇,不需要预先指定簇的数量。
- 能够识别噪声点,将它们标记为噪声或离群值。
-
缺点:
- 对于高维数据集,由于维度灾难的影响,性能可能较差。
- 对于密度差异很大的数据集,需要仔细选择参数。
-
应用场景:
- 图像分割:将相邻像素点中相似的像素聚合在一起,形成物体或区域。
- 社交网络分析:发现社交网络中的社区结构。
- 地理信息系统:识别地理空间数据中的簇。
总之,DBSCAN是一种强大的聚类算法,可以用于发现不同形状和密度的簇,并且对于噪声点的处理效果也较好。在应对具有复杂结构和未知簇数量的数据集时,它是一种有力的工具。然而,在使用DBSCAN时,需要谨慎选择合适的参数,以获得良好的聚类结果。
* 能用分类的就不要用聚类
"能用分类的就不要用聚类" 是一种常见的数据分析原则,它表明在某些情况下,分类(Supervised Learning)可能是更好的选择,而不是使用聚类(Unsupervised Learning)方法。这个原则的背后有一些原因:
-
目标不同:分类和聚类有不同的目标。分类的目标是为每个数据点分配一个预定义的标签或类别,而聚类的目标是将数据点分组成具有相似性质的簇,而不需要事先知道这些簇的数量或具体标签。
-
监督信息:在分类中,通常使用已知的标签或类别信息进行训练,这是一种监督学习方法。这个监督信息有助于算法学习如何正确地分配标签。在聚类中,没有监督信息可用,算法只能依赖数据的内在结构。
-
任务差异:分类通常用于解决有明确定义的预测问题,如图像识别、垃圾邮件分类等。聚类通常用于数据探索、分组或发现隐藏模式。
-
性能度量:在分类中,通常可以使用准确率、精确度、召回率等明确的性能度量来评估模型的质量。在聚类中,由于缺乏明确的标签,性能度量通常更加模糊和主观。
-
有监督学习更强大:有监督学习方法通常更强大,因为它们可以利用大量的标记数据来训练模型,从而提供更好的泛化性能。
尽管以上原则存在,但也有一些情况下可以考虑使用聚类方法:
- 当没有可用的标签数据或标签数据非常有限时,聚类可以用于探索数据的结构。
- 当数据的真实结构未知,并且没有明确的预测任务时,聚类可以帮助发现潜在的数据模式。
- 聚类可以用于数据预处理的步骤,以便在应用有监督学习算法之前更好地理解数据。
最终,选择使用分类还是聚类取决于具体的数据和问题背景。在实际应用中,通常需要考虑数据的性质、可用的信息以及任务的需求来确定使用哪种方法。