在copy代码之前,先来对k-means和dbscan算法进行简单的了解一下吧。
K-means聚类算法也称k均值聚类算法,是集简单和经典于一身的基于距离的聚类算法。它采用距离作为相似性的评价指标,即认为两个对象的距离越近,其相似度就越大。该算法认为类簇是由距离靠近的对象组成的,因此把得到紧凑且独立的簇作为最终目标。
K-means聚类算法是一种迭代求解的聚类分析算法,其步骤是随机选取K个对象作为初始的聚类中心,然后计算每个对象与各个种子聚类中心之间的距离,把每个对象分配给距离它最近的聚类中心。聚类中心以及分配给它们的对象就代表一个聚类。每分配一个样本,聚类的聚类中心会根据聚类中现有的对象被重新计算。这个过程将不断重复直到满足某个终止条件。终止条件可以是没有(或最小数目)对象被重新分配给不同的聚类,没有(或最小数目)聚类中心再发生变化,误差平方和局部最小。
1、首先确定一个k值,即我们希望将数据集经过聚类得到k个集合。
2、从数据集中随机选择k个数据点作为质心。
3、对数据集中每一个点,计算其与每一个质心的距离(如欧式距离),离哪个质心近,就划分到那个质心所属的集合。
4、把所有数据归好集合后,一共有k个集合。然后重新计算每个集合的质心。
5、如果新计算出来的质心和原来的质心之间的距离小于某一个设置的阈值(表示重新计算的质心的位置变化不大,趋于稳定,或者说收敛),我们可以认为聚类已经达到期望的结果,算法终止。
6、如果新质心和原质心距离变化很大,需要迭代3~5步骤。
DBSCAN是一个比较有代表性的基于密度的聚类算法。与划分和层次聚类方法不同,它将簇定义为密度相连的点的最大集合,能够把具有足够高密度的区域划分为簇,并可在噪声的空间数据库中发现任意形状的聚类。
· eps (ε):一种距离度量,用于定位任何点的邻域内的点。
· minPts:聚类在一起的点的最小数目(一个阈值),使一个区域界定为密集。
密度方面的可达性(Reachability)建立了一个可以到达另一个点的点,如果该点位于与另一个点的特定距离(eps)内。
连接性(Connectivity)涉及到基于传递性的链接方法,以确定点是否位于特定的聚类中。例如,如果p->r->s->t->q,则p和q可以连接,其中a->b表示b在a的邻域内。
优点:
1、与K-means方法相比,DBSCAN不需要事先知道要形成的簇类的数量。
2、与K-means方法相比,DBSCAN可以发现任意形状的簇类,而且能够识别出噪声点。
3、DBSCAN对于数据库中样本的顺序不敏感,即Pattern的输入顺序对结果的影响不大。但是,对于处于簇类之间边界样本,可能会根据哪个簇类优先被探测到而其归属有所摆动。
缺点:
1、DBSCAN不能很好反映高维数据。
2、DBSCAN不能很好反映数据集以变化的密度。
3、如果样本集的密度不均匀、聚类间距差相差很大时,聚类质量较差。
# -*- coding: utf-8 -*-
# !/usr/bin/env python
'''
数据集:鸢尾花数据(150)
模型:k-means、dbscan
'''
from sklearn.datasets import load_iris
from sklearn.preprocessing import MinMaxScaler
from sklearn.cluster import KMeans, DBSCAN
from sklearn.externals import joblib
from sklearn.cross_validation import train_test_split
import matplotlib.pyplot as plt
class cluster(object):
def __init__(self, path):
self.path = path
self.train_model(self.path)
self.test_model(self.path)
# 训练模型
def train_model(self, paths):
print("数据预处理")
self.iris = load_iris()
self.iris_data = self.iris['data']
self.iris_target = self.iris['target']
self.train_data, self.test_data, self.train_label, self.test_label = \
train_test_split(self.iris_data, self.iris_target, test_size=0.3, random_state=43)
self.scale = MinMaxScaler().fit(self.train_data)
self.iris_dataScale = self.scale.transform(self.train_data)
print("训练k-means模型")
self.kmeans = KMeans(n_clusters=3, random_state=9).fit(self.iris_dataScale)
print("训练dbscan模型")
self.dbscan = DBSCAN(eps=0.5, min_samples=5).fit(self.iris_dataScale)
# plt绘制kmeans聚类图
plt.figure(figsize=(16, 8))
plt.subplot(121)
y_pred = self.kmeans.predict(self.test_data)
plt.scatter(self.test_data[:, 0], self.test_data[:, 1], c=y_pred)
plt.title('kmeans')
# plt绘制dbscan聚类图
plt.figure(figsize=(16, 8))
plt.subplot(121)
y_pred = self.dbscan.fit_predict(self.test_data)
plt.scatter(self.test_data[:, 0], self.test_data[:, 1], c=y_pred)
plt.title('dbscan')
plt.show()
print("保存模型")
# 可以保存dbscan或者kmeans两种模型
# self.save_model(self.kmeans, paths)
self.save_model(self.dbscan, paths)
# 保存模型
def save_model(self, model, paths):
joblib.dump(model, paths)
# 模型测试
def test_model(self, path):
print("评估模型")
model = joblib.load(path)
real = 0
for i in range(len(self.test_data)):
try:
result = model.predict([self.test_data[i]])[0]
if result == self.test_label[i]:
real += 1
else:
pass
except:
result = model.fit_predict([self.test_data[i]])[0]
if result == self.test_label[i]:
real += 1
else:
pass
print('准确率为{:.2%}'.format(real / len(self.test_label)))
if __name__ == '__main__':
result = cluster('train_model.pkl')