【机器学习】使用scikitLearn对数据进行聚类:Kmeans聚类算法的应用及密度聚类DBSCAN

36 篇文章 5 订阅
27 篇文章 3 订阅

无监督学习:
【机器学习】使用scikitLearn对数据进行聚类:Kmeans聚类算法及聚类效果评估
【机器学习】使用scikitLearn对数据进行聚类:高斯聚类GaussianMixture
【机器学习】使用scikitLearn对数据进行聚类:7种异常和新颖性检测方式

1.图像分割
使用聚类方法,将色值聚成8类,并将每个色点赋值成聚类中心的颜色:

from matplotlib.image import imread
#读取图片
image = imread(os.path.join(images_path, filename))
#将图片拉直
X = image.reshape(-1, 3)
kmeans = KMeans(n_clusters=8, random_state=42).fit(X)
#将每个实例色点替换成聚类中心
segmented_img = kmeans.cluster_centers_[kmeans.labels_]
#重新塑回图形宽高
segmented_img = segmented_img.reshape(image.shape)
segmented_imgs = []

在这里插入图片描述

2.聚类做参数的预处理

from sklearn.pipeline import Pipeline
#当使用pipeline的时候,自动调用前序处理的transform方法,这里调用transform后,将原始数据转化为到#各个聚类中心的距离,以提高最终分类的准确率
pipeline = Pipeline([
    ("kmeans", KMeans(n_clusters=50, random_state=42)),
    ("log_reg", LogisticRegression(multi_class="ovr", solver="lbfgs", max_iter=5000, random_state=42)),
])
pipeline.fit(X_train, y_train)

3.半监督学习Semi-Supervised:标签传播
当大量数据集中只有少部分带标签的类时,使用标签传播的方法,可以节约人力标注,其步骤为:
(1)使用聚类聚成n类,形成n个中心点。
(2)找出最接近每个中心点的实例,进行人为标注。

kmeans = KMeans(n_clusters=k, random_state=42)
X_digits_dist = kmeans.fit_transform(X_train)
#取出距离聚类中心最接近的实例,并进行人工标记的工作:
representative_digit_idx = np.argmin(X_digits_dist, axis=0)
X_representative_digits = X_train[representative_digit_idx]
#人工辨认并赋值模型:
y_representative_digits = np.array([
    0, 1, 3, 2, 7, 6, 4, 6, 9, 5,
    1, 2, 9, 5, 2, 7, 8, 1, 8, 6,
    3, 2, 5, 4, 5, 4, 0, 3, 2, 6,
    1, 7, 7, 9, 1, 8, 6, 5, 4, 8,
    5, 3, 3, 6, 7, 9, 7, 8, 4, 9])

(3)其它实例按照接近中心点的程度,进行标签扩散操作。

(4)由于远离中心的实例,可能含有噪声,并且特征不明显,所以将标签扩散至所有实例的方法,未必能很好的提升准确率,故选择一定的比例,将标签扩散至接近中心的实例。

#指定取最近的75%的数据点的值
percentile_closest = 75
#transform后的索引取值,可以理解为一种定式,找出每个类相对于其自身聚类中心的聚类
X_cluster_dist = X_digits_dist[np.arange(len(X_train)), kmeans.labels_]
for i in range(k):
    #是否在当前指定的第i个聚类里面
    in_cluster = (kmeans.labels_ == i)
    #拿出其距离
    cluster_dist = X_cluster_dist[in_cluster]
    #从小到大拿出前percentile_closest的数据点处的值(分位数)
    cutoff_distance = np.percentile(cluster_dist, percentile_closest)
    above_cutoff = (X_cluster_dist > cutoff_distance)
    #远距离的点聚类重置为-1
    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]
#使用ovr处理多分类问题
log_reg = LogisticRegression(multi_class="ovr", solver="lbfgs", max_iter=5000, random_state=42)
log_reg.fit(X_train_partially_propagated, y_train_partially_propagated)

密度聚类:密度聚类将高密度连续区域视为一个集群。
指定一个实例领域中包含的其它实例点的数目k,如果某个实例邻域数目大于k,则为核心实例;核心实例标记一个集群,如果该核心实例领域中有其它核心实例,则集群得到延伸。如果一个实例的邻域中没有实例,则该实例被标记为异常。

from sklearn.cluster import DBSCAN
#0.05为邻域大小
dbscan = DBSCAN(eps=0.05, min_samples=5)
dbscan.fit(X)
#查看聚类情况
dbscan.labels_
#查看核心实例情况
dbscan.components_
#得到核心实例的索引,当索引返回-1时,为异常值,
#其标记了哪些实例是核心实例
dbscan.core_sample_indices_

DBSCAN只有fit_predict方法,他无法独立预测新实例,需要和其它分类算法相配合。

from sklearn.neighbors import KNeighborsClassifier
#其原理是,训练集中50个最近的实例投票决定新实例的类别
knn = KNeighborsClassifier(n_neighbors=50)
#在聚类后转化为有标签的分类算法
knn.fit(dbscan.components_, dbscan.labels_[dbscan.core_sample_indices_])
X_new = np.array([[-0.5, 0], [0, 0.5], [1, -0.1], [2, 1]])
knn.predict(X_new)

问题在于,knn分类给每个实例一个类,没有像dbscan一样的异常标签,其解决方法是:

#得到新实例离自己最近实例的距离和该邻居在数据集中的的索引号(每个点的邻居的索引)
y_dist, y_pred_idx = knn.kneighbors(X_new, n_neighbors=1)
#不考虑距离的情况下,最近的距离应该同其一个类别,先取核心实例标签(训练时用核心点进行训练),再取所有预测结果
y_pred = dbscan.labels_[dbscan.core_sample_indices_][y_pred_idx]
#考虑距离时,点中和其它点距离大于0.2的点其预测类别标记为异常:
y_pred[y_dist > 0.2] = -1
y_pred.ravel()

密度聚类的特点是其对类别的形状不敏感,在距离阈值eps较小时,时间复杂度O(mlogm)。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

颢师傅

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值