在未知输出标签的输入集中,利用输入样本之间的某种联系,建立划分模式和逻辑,将输入样本划分成不同的群落。
一维: P(x1),Q(x2)
PQ=sqrt((x1-x2)^2)
二维:P(x1,y1),Q(x2,y2)
PQ=sqrt((x1-x2)^2+(y1-y2)^2)
三维:P(x1,y1,z1),Q(x2,y2,z2)
PQ=sqrt((x1-x2)^2+(y1-y2)^2+(z1-z2)^2)
N维:P(x1,x2,...,xn),Q(x1',x2',...,xn')
PQ=sqrt((x1-x1')^2+(x2-x2')^2+...+(xn-xn')^2)
欧几里得距离,欧氏距离
聚类中心:任意一个聚类成员与该聚类中心的距离一定小于该成员与其它聚类中心的距离——向心性。
几何中心:聚类中所有成员对应特征值的算术平均数表示的虚拟样本——抽象性。
理想聚类:聚类中心与几何中心重合。
在总样本空间中,随机选择K个样本作为初始聚类中心,计算所有样本距离每个聚类中心的欧氏距离,离哪个中心最近就隶属于该中心所表示的类别,这样就完成了一次聚类划分。针对所得到的每个聚类,计算其样本集的几何中心,如果几何中心与聚类中心不重合,以几何中心作为新的聚类中心重新计算每个样本与新中心的距离,得到新的聚类划分。再次计算其几何中心,直到每个聚类的几何中心与其划分所依据的聚类中心重合或足够接近为止。
聚类数K需要事先知道。
通过性能指标优选最好的K。
初始聚类中心的选择可能会影响到最终的聚类划分结果。
以最大间距原则选择初始聚类中心。
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import numpy as np
import sklearn.cluster as sc
import sklearn.metrics as sm
import matplotlib.pyplot as mp
x = []
with open('../../data/multiple3.txt', 'r') as f:
for line in f.readlines():
data = [float(substr) for substr
in line.split(',')]
x.append(data)
x = np.array(x)
model = sc.KMeans(n_clusters=4) # K(聚类数)=4
model.fit(x)
pred_y = model.labels_
centers = model.cluster_centers_
print(sm.silhouette_score(
x, pred_y, sample_size=len(x), metric="euclidean"))
l, r, h = x[:, 0].min() - 1, x[:, 0].max() + 1, 0.005
b, t, v = x[:, 1].min() - 1, x[:, 1].max() + 1, 0.005
grid_x = np.meshgrid(
np.arange(l, r, h), np.arange(b, t, v))
flat_x = np.c_[grid_x[0].ravel(), grid_x[1].ravel()]
flat_y = model.predict(flat_x)
grid_y = flat_y.reshape(grid_x[0].shape)
mp.figure('K-Means Cluster', facecolor='lightgray')
mp.title('K-Means Cluster', fontsize=20)
mp.xlabel('x', fontsize=14)
mp.ylabel('y', fontsize=14)
mp.tick_params(labelsize=10)
mp.pcolormesh(grid_x[0], grid_x[1], grid_y,
cmap='gray')
mp.scatter(x[:, 0], x[:, 1], c=pred_y, cmap='brg',
s=60)
mp.scatter(centers[:, 0], centers[:, 1], marker='+',
c='gold', s=1000, linewidth=1)
mp.show()
图像量化
y = [0 0 1 1 2 2 3 3]
centers = [100 200 300 400]
image2 = [100 100 200 200 300 300 400 400]
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import numpy as np
import scipy.misc as sm
import sklearn.cluster as sc
import matplotlib.pyplot as mp
image1 = sm.imread('../../data/lily.jpg',
True).astype(np.uint8)
x = image1.reshape(-1, 1)
model = sc.KMeans(n_clusters=4)
model.fit(x)
y = model.labels_
centers = model.cluster_centers_.squeeze()
image2 = centers[y].reshape(image1.shape)
model = sc.KMeans(n_clusters=3)
model.fit(x)
y = model.labels_
centers = model.cluster_centers_.squeeze()
image3 = centers[y].reshape(image1.shape)
model = sc.KMeans(n_clusters=2)
model.fit(x)
y = model.labels_
centers = model.cluster_centers_.squeeze()
image4 = centers[y].reshape(image1.shape)
mp.figure('Image Quantization', facecolor='lightgray')
mp.subplot(221)
mp.title('Original', fontsize=16)
mp.axis('off')
mp.imshow(image1, cmap='gray')
mp.subplot(222)
mp.title('Quanted-4', fontsize=16)
mp.axis('off')
mp.imshow(image2, cmap='gray')
mp.subplot(223)
mp.title('Quanted-3', fontsize=16)
mp.axis('off')
mp.imshow(image3, cmap='gray')
mp.subplot(224)
mp.title('Quanted-2', fontsize=16)
mp.axis('off')
mp.imshow(image4, cmap='gray')
mp.tight_layout()
mp.show()
将待划分聚类的样本空间看做服从某种统计规则的随机分布,利用已知概率密度曲线(面)拟合样本的统计直方图,由匹配度最佳的概率密度曲线(面)峰值可以确定每个聚类的中心位置,然后再根据每个样本距离各个聚类中心的远近,划分不同的聚类。
均值漂移算法可以根据随机分布样本的疏密程度,自动识别聚类的个数(K),因此对于事先不知道聚类数,同时又没有显著几何中心特征的样本集,使用均值漂移算法具有明显的优势。
K均值算法的聚类中心——几何中心---------\ 基于中心
均值漂移算法的聚类中心——随机分布中心 / 的预测(predict)
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import numpy as np
import sklearn.cluster as sc
import matplotlib.pyplot as mp
x = []
with open('../../data/multiple3.txt', 'r') as f:
for line in f.readlines():
data = [float(substr) for substr
in line.split(',')]
x.append(data)
x = np.array(x)
bw = sc.estimate_bandwidth(
x, n_samples=len(x), quantile=0.1)
model = sc.MeanShift(bandwidth=bw, bin_seeding=True)
model.fit(x)
pred_y = model.labels_
centers = model.cluster_centers_
l, r, h = x[:, 0].min() - 1, x[:, 0].max() + 1, 0.005
b, t, v = x[:, 1].min() - 1, x[:, 1].max() + 1, 0.005
grid_x = np.meshgrid(
np.arange(l, r, h), np.arange(b, t, v))
flat_x = np.c_[grid_x[0].ravel(), grid_x[1].ravel()]
flat_y = model.predict(flat_x)
grid_y = flat_y.reshape(grid_x[0].shape)
mp.figure('Mean Shift Cluster', facecolor='lightgray')
mp.title('Mean Shift Cluster', fontsize=20)
mp.xlabel('x', fontsize=14)
mp.ylabel('y', fontsize=14)
mp.tick_params(labelsize=10)
mp.pcolormesh(grid_x[0], grid_x[1], grid_y,
cmap='gray')
mp.scatter(x[:, 0], x[:, 1], c=pred_y, cmap='brg',
s=60)
mp.scatter(centers[:, 0], centers[:, 1], marker='+',
c='gold', s=1000, linewidth=1)
mp.show()
首先假定每个样本都是独立的聚类,计算聚类数,若其大于实现给定的聚类数,则将这些样本按照距离最近原则,两两结合,形成较少的聚类,重复以上过程,直到聚类数达到预期为止。
实现给定聚类数。
没有聚类中心,无法对训练集以外的样本进行类别预测。
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import numpy as np
import sklearn.cluster as sc
import sklearn.metrics as sm
import matplotlib.pyplot as mp
x = []
# with open('../../data/multiple3.txt', 'r') as f:
with open('../../data/perf.txt', 'r') as f:
for line in f.readlines():
data = [float(substr) for substr
in line.split(',')]
x.append(data)
x = np.array(x)
clstrs, scores, models = np.arange(2, 11), [], []
for n_clusters in clstrs:
model = sc.AgglomerativeClustering(
n_clusters=n_clusters)
model.fit(x)
score = sm.silhouette_score(
x, model.labels_, sample_size=len(x),
metric='euclidean')
scores.append(score)
models.append(model)
pred_y = models[np.array(scores).argmax()].labels_
mp.figure('Agglomerative Cluster',
facecolor='lightgray')
mp.title('Agglomerative Cluster', fontsize=20)
mp.xlabel('x', fontsize=14)
mp.ylabel('y', fontsize=14)
mp.tick_params(labelsize=10)
mp.grid(linestyle=':')
mp.scatter(x[:, 0], x[:, 1], c=pred_y, cmap='brg',
s=60)
mp.show()
基于距离的凝聚——块状凝聚
基于连续性的凝聚——线状凝聚
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import numpy as np
import sklearn.cluster as sc
import sklearn.neighbors as nb
import matplotlib.pyplot as mp
n_samples = 500
t = 2.5 * np.pi * (1 + 2 * np.random.rand(
n_samples, 1))
x = 0.05 * t * np.cos(t)
y = 0.05 * t * np.sin(t)
n = 0.05 * np.random.rand(n_samples, 2)
x = np.hstack((x, y)) + n
model = sc.AgglomerativeClustering(
linkage='average', n_clusters=3)
pred_y1 = model.fit_predict(x)
model = sc.AgglomerativeClustering(
linkage='average', n_clusters=3,
connectivity=nb.kneighbors_graph(
x, 10, include_self=False))
pred_y2 = model.fit_predict(x)
mp.figure('Agglomerative Cluster 1',
facecolor='lightgray')
mp.title('Agglomerative Cluster 1', fontsize=20)
mp.xlabel('x', fontsize=14)
mp.ylabel('y', fontsize=14)
mp.tick_params(labelsize=10)
mp.grid(linestyle=':')
mp.axis('equal')
mp.scatter(x[:, 0], x[:, 1], c=pred_y1, cmap='brg',
alpha=0.5, s=60)
mp.figure('Agglomerative Cluster 2',
facecolor='lightgray')
mp.title('Agglomerative Cluster 2', fontsize=20)
mp.xlabel('x', fontsize=14)
mp.ylabel('y', fontsize=14)
mp.tick_params(labelsize=10)
mp.grid(linestyle=':')
mp.axis('equal')
mp.scatter(x[:, 0], x[:, 1], c=pred_y2, cmap='brg',
alpha=0.5, s=60)
mp.show()
好聚类一定是内密外疏的聚类。
通过轮廓系数表示聚类内密外疏的程度,即聚类器的性能。
一个样本的轮廓系数:s = (b-a)/max(a,b), (-1, 1)
a:该样本与同聚类的其它样本的平均距离,即内部距离。
b:该样本与离它所属聚类最接近的另一个聚类中各样本的平均距离,即外部距离。
聚类模型的轮廓系数:S = ave(s), (-1, 1)
->-1:错误聚类
->1:理想聚类
->0:聚类重叠
sm.silhouette_score(输入, 输出, sample_size=样本数,
metric='euclidean')->轮廓系数得分
朋友的朋友也是朋友。
从任意一个样本出发,做以该样本为圆心,给定半径做圆,被该圆圈中的样本与该样本归属同一个聚类,再以这些被圈中的样本为圆心,按照同样的方法继续做圆,以囊括更多的样本加入该聚类,直到再没有新样本加入为止,即完成了一个聚类的划分。从剩余样本中任选一个,重复以上过程,以划分其它聚类,直到再没有未使用的样本为止。
根据轮廓系数得分选择最优的划分半径。
核心样本:用能力向所在聚类引入新样本的样本。
外周样本:虽然身在聚类之内,但是无法再引入新的样本。
孤立样本:所在聚类的规模太小,无法超过最小阈值。
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import numpy as np
import sklearn.cluster as sc
import sklearn.metrics as sm
import matplotlib.pyplot as mp
x = []
with open('../../data/perf.txt', 'r') as f:
for line in f.readlines():
data = [float(substr) for substr
in line.split(',')]
x.append(data)
x = np.array(x)
epsilons, scores, models = \
np.linspace(0.3, 1.2, 10), [], []
for epsilon in epsilons:
# eps - 朋友圈半径
# min_samples - 聚类规模最小阈值
model = sc.DBSCAN(eps=epsilon, min_samples=5)
model.fit(x)
score = sm.silhouette_score(
x, model.labels_, sample_size=len(x),
metric='euclidean')
scores.append(score)
models.append(model)
best_model = models[np.array(scores).argmax()]
pred_y = best_model.labels_
core_mask = np.zeros(len(x), dtype=bool)
core_mask[best_model.core_sample_indices_] = True
offset_mask = pred_y == -1
periphery_mask = ~(core_mask | offset_mask)
mp.figure('DBSCAN Cluster', facecolor='lightgray')
mp.title('DBSCAN Cluster', fontsize=20)
mp.xlabel('x', fontsize=14)
mp.ylabel('y', fontsize=14)
mp.tick_params(labelsize=10)
mp.grid(linestyle=':')
labels = set(pred_y)
# 0 1 2 3 4 5
# |---|---|---|---|---|---|
# B-----------R-----------G
cs = mp.get_cmap('brg', len(labels))(
range(len(labels)))
mp.scatter(x[core_mask][:, 0],
x[core_mask][:, 1],
c=cs[pred_y[core_mask]],
s=60, label='Core')
mp.scatter(x[periphery_mask][:, 0],
x[periphery_mask][:, 1],
edgecolor=cs[pred_y[periphery_mask]],
facecolor='none',
s=60, label='Periphery')
mp.scatter(x[offset_mask][:, 0],
x[offset_mask][:, 1],
marker='x',
c=cs[pred_y[offset_mask]],
s=60, label='Offset')
mp.legend()
mp.show()
想要看更多的课程请微信关注SkrEric的编程课堂