K-Mediods算法
1. 实验目标
学习并使用 k k k- m e d o i d s medoids medoids算法,了解该算法的优缺点
2. 实验主要使用的 P y t h o n Python Python 库
名称 | 版本 | 简介 |
---|---|---|
N u m p y Numpy Numpy | 1.16.0 1.16.0 1.16.0 | 线性代数 |
P a n d a s Pandas Pandas | 0.25.0 0.25.0 0.25.0 | 数据分析 |
M a t p l o t l i b Matplotlib Matplotlib | 3.1.0 3.1.0 3.1.0 | 数据可视化 |
S K l e a r n SKlearn SKlearn | 0.22.1 0.22.1 0.22.1 | 机器学习 |
3. 实验步骤
步骤1 安装并导入所需要的库
!pip install numpy==1.16.0
!pip install pandas==0.25.0
!pip install scikit-learn==0.22.1
!pip install matplotlib==3.1.0
!pip install treelib
!pip install pyclust
from sklearn.datasets import make_blobs
from matplotlib import pyplot
import numpy as np
import random
步骤2 定义一个k-medoid类
定义一个k-medoid类,__init__方法定义参数
2.1 创建测试数据并画图显示
scikit中的make_blobs方法常被用来生成聚类算法的测试数据,直观地说,make_blobs会根据用户指定的特征数量、中心点数量、范围等来生成几类数据,这些数据可用于测试聚类算法的效果。
- @ param n_samples : 表示多少个点,
- @ param n_features : 表示几维
- @ param centers : 得到的data是n个点各自坐标
- @ param target : 每个坐标的分类(若我规定好四个分类,target长度为n范围为0-3,主要是画图颜色区别)
2.2 定义欧式距离的计算
2.3 K-mediods算法
- @ param func_of_dis :距离公式
2.4 画图分类比较
获取数据并画图展示开始未分类的图,展示分类后的图。
代码:
class KMediod():
def __init__(self, n_points, k_num_center):
self.n_points = n_points
self.k_num_center = k_num_center
self.data = None
def get_test_data(self):
self.data, target = make_blobs(n_samples=self.n_points, n_features=2, centers=self.n_points)
np.put(self.data, [self.n_points, 0], 500, mode='clip')
np.put(self.data, [self.n_points, 1], 500, mode='clip')
pyplot.scatter(self.data[:, 0], self.data[:, 1], c=target)
# 画图
pyplot.show()
def ou_distance(self,x, y):
return np.sqrt(sum(np.square(x - y)))
def run_k_center(self,func_of_dis):
print('初始化', self.k_num_center, '个中心点')
indexs = list(range(len(self.data)))
random.shuffle(indexs) # 随机选择质心
init_centroids_index = indexs[:self.k_num_center]
centroids = self.data[init_centroids_index, :] # 初始中心点
levels = list(range(self.k_num_center)) # 确定种类编号
print('开始迭代')
sample_target = []
if_stop = False # 用来判断聚类是否已经收敛
while(not if_stop):
if_stop = True
classify_points = [[centroid] for centroid in centroids]
sample_target = []
# 遍历数据
for sample in self.data:
# 计算距离,由距离该数据最近的核心,确定该点所属类别
distances = [func_of_dis(sample, centroid) for centroid in centroids]
cur_level = np.argmin(distances)
sample_target.append(cur_level)
classify_points[cur_level].append(sample) # 统计,方便迭代完成后重新计算中间点
# 重新划分质心
for i in range(self.k_num_center): # 几类中分别寻找一个最优点
distances = [func_of_dis(point_1, centroids[i]) for point_1 in classify_points[i]]
now_distances = sum(distances) # 首先计算出现在中心点和其他所有点的距离总和
for point in classify_points[i]:
distances = [func_of_dis(point_1, point) for point_1 in classify_points[i]]
new_distance = sum(distances)
# 计算出该聚簇中各个点与其他所有点的总和,若是有小于当前中心点的距离总和的,中心点去掉
if new_distance < now_distances:
now_distances = new_distance
centroids[i] = point # 换成该点
if_stop = False
print('结束')
return sample_target
def run(self):
self.get_test_data()
predict = self.run_k_center(self.ou_distance)
pyplot.scatter(self.data[:, 0], self.data[:, 1], c=predict)
pyplot.show()
test=KMediod(n_points=1000, k_num_center=3)
test.run()
在构造初始点的时候,自己定义加入了几个孤立点
一开始的所有点:(可以看出其他点是混在一起有许多分类的)
分类后的图:
步骤3 sklearn实现K-Medoids算法
3.1 引入所需要的库
from pyclust import KMedoids
import numpy as np
from sklearn.manifold import TSNE
import matplotlib.pyplot as plt
3.2构造示例数据集(加入少量脏数据)
data1 = np.random.normal(0,0.9,(1000,10))
data2 = np.random.normal(1,0.9,(1000,10))
data3 = np.random.normal(2,0.9,(1000,10))
data4 = np.random.normal(3,0.9,(1000,10))
data5 = np.random.normal(50,0.9,(50,10))
data = np.concatenate((data1,data2,data3,data4,data5))
3.3 准备可视化需要的降维数据
data_TSNE = TSNE(learning_rate=100).fit_transform(data)
3.4 对不同的k进行试探性K-medoids聚类并可视化
plt.figure(figsize=(12,8))
for i in range(2,6):
k = KMedoids(n_clusters=i,distance='euclidean',max_iter=1000).fit_predict(data)
colors = ([['red','blue','black','yellow','green'][i] for i in k])
plt.subplot(219+i)
plt.scatter(data_TSNE[:,0],data_TSNE[:,1],c=colors,s=10)
plt.title('K-medoids Resul of '.format(str(i)))