【机器学习实战】Ch 9:无监督学习 技术

K-Means

from sklearn.cluster import KMeans
k = 5
kmeans = KMeans(n_clusters=k)
y_pred = kmeans.predict(X)

# 算法的k个中心点
kmeans.cluster_centers_

# 每个实例到中心点距离 (软聚类)
kmeans.transform(X)

# 训练实例的标签副本
kmeans.labels_

中心点初始化方法

如果事先知道了中心点位置, 可以将超参数init设置为中心点列表的NumPy数组

good_init = np.array([[-3, 3], [-3, 2], [-3, 1], [-1, 2], [0, 2]])
kmeans = KMeans(n_clusters=5, init=good_init, n_init=1)

另一种方案:使用不同的随机化运行多次算法, 保留最优解。 随机初始化的数量由超参数n_init控制:默认情况为10。 性能的指标称为模型的惯性, 为每个实例与其最近的中心点的均方距离。 可以通过kmeans.inertia访问, score()返回负惯性。

加速的K-Means和小批量K-Means

加速的K-Means 默认使用, 通过三角不等式并跟踪实例和中心点之间上下限距离来实现。

小批量K-Means, 速度更快, 但惯性更差一些

from sklearn.cluster import MiniBatchKMeans

minibatch_kmeans = MiniBatchKMeans(n_clusters=5)
minibatch_kmeans.fit(X)

寻找最佳聚类数

粗糙方案:绘制惯性作为集群k的函数曲线, 曲线通常包含一个称为“肘”的拐点, 可以将其作为聚类数的选择。

更精确的方案:轮廓分数(所有实例的平均轮廓系数)

实例的轮廓系数:  (b-a)/ max(a, b)
a :  集群内平均距离, 即与同一集群中其他实例的平均距离
b :  平均最近集群距离, 即到下一个最近集群的平均距离, 定义b是最小的那个,不包括实例自身的集群
轮廓系数 ∈ [-1+1]
接近+1的系数表示该实例很好的位于自身的集群中, 并且远离其他集群
接近 0的系数表示该实例接近一个集群的边界
接近-1的系数表示该实例可能已经分配给了错误的集群
# 计算轮廓分数
from sklearn.metrics import silhouette_score
silhouette_score(X, kmeans.labels_)

使用聚类进行图像分割

# 加载图像
from matplotlib.image import imread
image = imread(os.path.join("image", "unsuperised_learning", "ladybug.png"))

# 将颜色聚类
X = image.reshape(-1, 3)
kmeans = KMeans(n_clusters=8).fit(X)
segmented_img = kmeans.cluster_centers_[kmeans.labels_]
segmented_img = segmented_img.reshape(image.shape)

使用聚类进行预处理

# 例子:处理数字数据集
# 加载数据集
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)# 拟合逻辑回归模型
from sklearn.linear_model import LogisticRegression
log_reg = LogisticRegression()
log_reg.fit(X_train, y_train)

# 测试集上评估精度
>>> log_reg.score(X_test, y_test)
0.96    # 以此为基准
# 用kmeans作为预处理
from sklearn.pipeline import Pipeline
from sklearn.cluster import KMeans

pipeline = Pipeline([
    ("kmeans", KMeans(n_clusters=50)),
    ("log_reg", LogisticRegression())
])
pipeline.fit(X_train, y_train)

>>> pipeline.score(X_test, y_test)
0.9622222222222222
# 网格搜索k最优解, 及此时的性能
from sklearn.model_selection import GridSearchCV

param_grid = dict(kmeans__n_clusters=range(2, 100))
grid_clf = GridSearchCV(pipeline, param_grid, cv=3, verbose=2)
grid_clf.fit(X_train, y_train)

>>> grid_clf.best_params_
{'kmeans__n_clusters': 86}

>>> grid_clf.score(X_test, y_test)
0.9644444444444444

使用聚类进行半监督学习

DBSCAN

工作原理:

# 对于每个实例, 计算距它一小段距离epsilon内有多少实例。该区域称为实例的epsilon-邻域

# 如果一个实例在其epsilon邻域中至少包含min_samples个实例(包括自身), 则该实例视为核心实例

# 核心邻域的所有实例都属于同一集群。 这个邻域可能包含其他核心实例, 因此, 一长串相邻的核心实例形成一个集群。

# 任何不是核心实例且邻居中没有实例的实例都被视为异常 
from sklearn.cluster import DBSCAN
from sklearn.datasets import make_moons

X, y = make_moons(n_samples=1000, noise=0.05)
dbscan = DBSCAN(eps=0.05, min_samples=5)
dbscan.fit(X)
>>>dbscan.labels_
array([ 0,  1,  2, -1,  1,  3,  4,  0,  1,  1],  dtype=int64)
# 集群索引为-1的实例视为异常

# 核心实例的索引
>>>dbscan.core_sample_indices_
array([  0,   1,   2,   4, 997, 998, 999], dtype=int64)

# 核心实例本身
>>> dbscan.components_
array([[-0.61335521,  0.75630075],
       [ 0.18891419,  0.96079214],
       [ 1.71429492, -0.282264  ],
       ...,
       [-0.65099898,  0.64982719],
       [ 1.02107467,  0.13306044],
       [-0.33691843,  0.9684963 ]])

DBSCAN有fit_predict()方法, 但不具有predict()方法, 由用户选择分类算法

from sklearn.neighbors import KNeighborsClassifier

knn = KNeighborsClassifier(n_neighbors=50)
knn.fit(dbscan.components_, dbscan.labels_[dbscan.core_sample_indices_])

import numpy as np
X_new = np.array([[-0.5, 0], [0, 0.5], [1, -0.1], [2, 1]])

>>> knn.predict(X_new)
array([7, 4, 1, 9], dtype=int64)
>>> knn.predict_proba(X_new)
array([[0.  , 0.  , 0.  , 0.  , 0.08, 0.06, 0.  , 0.64, 0.22, 0.  , 0.  ],
       [0.  , 0.  , 0.  , 0.  , 1.  , 0.  , 0.  , 0.  , 0.  , 0.  , 0.  ],
       [0.  , 0.76, 0.  , 0.  , 0.  , 0.  , 0.24, 0.  , 0.  , 0.  , 0.  ],
       [0.  , 0.  , 0.  , 0.  , 0.  , 0.  , 0.  , 0.  , 0.  , 1.  , 0.  ]])

高斯混合模型

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值