环境:
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)
# 导入所需库
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得到每个样本到各个簇中心的距离
# 定义绘制数据点的函数
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() # 显示图形
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均值模型实例:
kmeans_iter1
、kmeans_iter2
和 kmeans_iter3
。拟合模型:
X
进行拟合,通过不同的迭代次数来演示模型在不同迭代阶段的效果。可视化:
plot_data
函数绘制数据点,使用 plot_centroids
函数绘制聚类中心,使用 plot_decision_boundaries
函数绘制决策边界。显示图形:
plt.show()
来显示包含多个子图的图形窗口,以便比较不同迭代次数下的K均值聚类效果。总的来说,该代码演示了K均值聚类算法的迭代过程,通过逐步调整聚类中心来逼近数据的簇结构,并可视化不同迭代次数下的聚类结果,帮助理解K均值聚类的工作原理。
# 定义一个函数,用于比较两个不同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均值聚类不稳定结果的简要概述:
初始聚类中心的随机性:
init='random'
参数来随机初始化聚类中心,不同的随机种子(random_state
)可能会导致不同的初始中心点,进而影响最终的聚类结果。算法的随机性:
多次运行和结果比较:
总之,K均值聚类在某些情况下可能产生不稳定的结果,这是由于其初始聚类中心的随机性和算法的随机性所导致的。为了得到可靠的聚类结果,通常需要进行多次运行和结果比较,以选择最优的聚类解决方案。
Inertia(内部距离平方和)是K均值聚类中常用的一种评估指标,用于衡量聚类结果的紧密度。以下是对Inertia的简要概述:
Inertia的计算:
Inertia的含义:
评估聚类结果:
在提供的代码示例中,通过 kmeans.inertia
可以获取K均值聚类模型的Inertia值,用于评估当前的聚类效果。较低的Inertia值表示更好的聚类结果。
# 创建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值:
计算Inertia值:
绘制Inertia值图表:
选择肘部点:
注意调整范围:
总之,通过绘制Inertia值随K值变化的图表并找到肘部点,可以帮助选择合适的K值,从而获得最佳的K均值聚类结果。
结论:
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)是一种用于评估聚类结果质量的指标,其作用可以简要概述如下:
度量簇内紧密度和簇间分离度:
取值范围和解释:
作为聚类质量的度量标准:
选择最佳簇数量:
总之,轮廓系数是一种有用的聚类评估指标,可以帮助衡量聚类结果的紧密度和分离度,以及选择最佳的簇数量。通过轮廓系数,可以更好地理解和选择适合数据的聚类解决方案。
# 导入所需库
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均值算法存在的问题:
初始聚类中心的选择问题:
Inertia值不一定准确:
解决方法:
总之,K均值算法存在对初始聚类中心选择敏感的问题,导致不同的初始化可能会产生不同的聚类结果,这需要谨慎处理。因此,在使用K均值算法时,需要考虑多次运行并结合其他评估指标来评估聚类结果的稳定性和准确性。
# 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均值算法在图像分割中的应用:
不同簇数的影响:
n_colors
),可以得到不同颜色数量的分割图像。实际应用:
总之,K均值算法在图像分割中的应用示例演示了如何使用聚类方法将图像像素划分成不同的簇,以实现图像的分割和处理。这是计算机视觉中的一个重要任务,可以帮助解决各种图像分析和处理问题。
首先,让我们将训练集聚类为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
以上代码演示了半监督学习的应用示例,特别是在手写数字分类任务中。以下是半监督学习的用法和意义的简要概述:
半监督学习的用法:
示例中的应用:
半监督学习的意义:
总之,半监督学习是一种有用的机器学习方法,可以在有限的有标签数据下提高模型性能,并应用于各种领域,以更好地利用未标签数据和降低数据标记的成本。
# 导入所需库
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)是一种密度聚类算法,其用法和作用可以简要概括如下:
用途:
工作原理:
min_samples
参数决定)的邻居样本点,才会形成一个簇。参数说明:
eps
:用于定义邻域的半径,表示一个样本点到其邻居点的最大距离。min_samples
:定义核心点所需的最小邻居样本数。优点:
缺点:
应用场景:
总之,DBSCAN是一种强大的聚类算法,可以用于发现不同形状和密度的簇,并且对于噪声点的处理效果也较好。在应对具有复杂结构和未知簇数量的数据集时,它是一种有力的工具。然而,在使用DBSCAN时,需要谨慎选择合适的参数,以获得良好的聚类结果。
"能用分类的就不要用聚类" 是一种常见的数据分析原则,它表明在某些情况下,分类(Supervised Learning)可能是更好的选择,而不是使用聚类(Unsupervised Learning)方法。这个原则的背后有一些原因:
目标不同:分类和聚类有不同的目标。分类的目标是为每个数据点分配一个预定义的标签或类别,而聚类的目标是将数据点分组成具有相似性质的簇,而不需要事先知道这些簇的数量或具体标签。
监督信息:在分类中,通常使用已知的标签或类别信息进行训练,这是一种监督学习方法。这个监督信息有助于算法学习如何正确地分配标签。在聚类中,没有监督信息可用,算法只能依赖数据的内在结构。
任务差异:分类通常用于解决有明确定义的预测问题,如图像识别、垃圾邮件分类等。聚类通常用于数据探索、分组或发现隐藏模式。
性能度量:在分类中,通常可以使用准确率、精确度、召回率等明确的性能度量来评估模型的质量。在聚类中,由于缺乏明确的标签,性能度量通常更加模糊和主观。
有监督学习更强大:有监督学习方法通常更强大,因为它们可以利用大量的标记数据来训练模型,从而提供更好的泛化性能。
尽管以上原则存在,但也有一些情况下可以考虑使用聚类方法:
最终,选择使用分类还是聚类取决于具体的数据和问题背景。在实际应用中,通常需要考虑数据的性质、可用的信息以及任务的需求来确定使用哪种方法。