聚类是一种无监督学习。与分类不同的是,分类的数据集都是有标签的已经指明了该样本是哪一类,而对于聚类其数据集样本是没有标签的,需要我们根据特征对这些数据进行聚类。
K-Means算法是一种无监督学习的聚类方法。

1.K-Means算法

算法接受参数K,然后将事先输入的n个数据对象划分成K个聚类以便使得所获得得聚类满足:同一聚类中得对象相似的较高,而不同聚类中的对象相似度较小。
算法思想:以空间中K个点为中心进行聚类,对著靠近他们得对象归类。通过迭代的方法,逐次更新聚类中心得值,直至得到最好的聚类结果。
K—MEANS算法步骤:
1.先从没有标签得元素集合A中随机取k个元素,作为k个子集各自的重心
2.分别计算剩下得元素到k个子集重心得距离(这里的距离也可以使用欧氏距离),根据距离将这些元素分别划归到最近的子集。
3.根据聚类得结果,重新计算重心((重心得计算方法是计算子集中所有元素各个维度得算数平均数)
4.将集合A中全部元素按照新的重心然后在重新聚类。
5.重复第4步,直到聚类结果不再发生改变。
举例:
在这里插入图片描述
以上边得数据为例,给定k=2,假设第一次我们选取得重心为(1,1)(2,1),分别计算所有得点到重心的距离,结果如下图的D0所示,按照每个元素到达重心的距离远近将其划分到相应的子集中,结果如G0所示;

在这里插入图片描述

在这里插入图片描述
在重新计算新的重心,对应第一个类别,由于就只有(1,1)一个点,所以其重心就是(1,1)本身,对于第二个类别其重心就是所以点的X,Y轴坐标分别相加求平均值,为c2。所以新的重心就变成了图上五角星所表示的点。
再次计算各个点到重心的距离得到D1,按照计算出来的距离进行划分得到新的划分结果G1,再次重新计算重心C1,c2。

接着照着上边的步骤进行计算得到D2,G2,发现聚类结果不再发生改变,聚类停止迭代。

python实现
1
2
import numpy as np
import matplotlib.pylab as plt
1
2
3
4
5
6
data=np.genfromtxt('kmeans.txt',delimiter=' ')
print(data.shape)
print(data[:5,:])

plt.scatter(data[:,0],data[:,1])
plt.show()
(80, 2)
[[ 1.658985  4.285136]
 [-3.453687  3.424321]
 [ 4.838138 -1.151539]
 [-5.379713 -3.362104]
 [ 0.972564  2.924086]]

png

1
2
def eucldistance(v1,v2):
return np.sqrt(sum((v2-v1)**2))
1
2
3
4
5
6
7
8
9
10
11
12
13
def initCenter(data,k):
numSanples,dim=data.shape
#获取样本行数和列数

center=np.zeros((k,dim))
#生成k个重心

for i in range(k):
index=int(np.random.uniform(0,numSanples))
#从0-79中随机选择一个索引
center[i,:]=data[index,:]
#初始化重心
return center
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
def kmeans(data,k):
numSamples=data.shape[0]#样本个数
#样本的属性,第一列表示它属于哪个簇,第二列表示它与该簇的误差(到重心的距离)
resultData=np.array(np.zeros((numSamples,2)))

isChange=True #聚类是否发生了改变

center=initCenter(data,k)
#初始化重心

while (isChange):
isChange=False

#对每个样本进行循环,计算器属于那个类别
for i in range(numSamples):
Mindist=10000
minindex=0
#先给一个很大的距离

for j in range(k):
distance=eucldistance(center[j,:],data[i,:])
#循环计算每一个样本点到每一个重心的距离

#如果计算出的距离小于当前最小距离,则对最小距离进行更新
if(distance<Mindist):
Mindist=distance
resultData[i,1]=distance
minindex=j#更新样本的簇

if resultData[i,0] !=minindex:#样本的簇发生了改变,需要继续更新
isChange=True#质心要重新计算
resultData[i,0]=minindex#更新样本的簇

for j in range(k):
# 获取第j个簇所有的样本所在的索引
cluster_index=np.nonzero(resultData[:,0]==j)
point=data[cluster_index]
#提取出第j簇的所有样本点
center[j,:]=np.mean(point,axis=0)
return center,resultData
1
2
3
4
test=np.array([0,1,2,3,1,0,2,3,1,2,0,1])
print(test==0)
print(np.nonzero(test==0))
print(test[np.nonzero(test==0)])
[ True False False False False  True False False False False  True False]
(array([ 0,  5, 10], dtype=int64),)
[0 0 0]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 显示结果 
def showCluster(data, k, centroids, resultData):
numSamples, dim = data.shape
if dim != 2:
print("dimension of your data is not 2!")
return 1

# 用不同颜色形状来表示各个类别
mark = ['or', 'ob', 'og', 'ok', '^r', '+r', 'sr', 'dr', '<r', 'pr']
if k > len(mark):
print("Your k is too large!")
return 1

# 画样本点
for i in range(numSamples):
markIndex = int(resultData[i, 0])
plt.plot(data[i, 0], data[i, 1], mark[markIndex])

# 用不同颜色形状来表示各个类别
mark = ['*r', '*b', '*g', '*k', '^b', '+b', 'sb', 'db', '<b', 'pb']
# 画质心点
for i in range(k):
plt.plot(centroids[i, 0], centroids[i, 1], mark[i], markersize = 20)

plt.show()
1
2
3
4
k=4#设置k
center,resultData=kmeans(data,k)
#计算重心和距离
showCluster(data,k,center,resultData)

png

1
center
array([[-3.68133264, -3.18226857],
       [ 2.39738441,  1.74393033],
       [ 3.104819  , -3.107608  ],
       [-2.5978898 ,  1.81264996]])
1
2
3
#做预测
def predict(datas):
return np.array([np.argmin(((np.tile(data,(k,1))-center)**2).sum(axis=1)) for data in datas])
1
2
3
4
x_test=[1,2]
a=np.tile(x_test,[k,1])
print(a)
print((a**2).sum(axis=1))
[[1 2]
 [1 2]
 [1 2]
 [1 2]]
[5 5 5 5]
1
2
3
4
5
6
7
8
9
10
11
12
# 获取数据值所在的范围
x_min, x_max = data[:, 0].min() - 1, data[:, 0].max() + 1
y_min, y_max = data[:, 1].min() - 1, data[:, 1].max() + 1

# 生成网格矩阵
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.02),
np.arange(y_min, y_max, 0.02))

z = predict(np.c_[xx.ravel(), yy.ravel()])# ravel与flatten类似,多维数据转一维。flatten不会改变原始数据,ravel会改变原始数据
z=z.reshape(xx.shape)
cs=plt.contourf(xx,yy,z)
showCluster(data,k,center,resultData)

png

sklearn实现
1
from sklearn.cluster import KMeans
1
2
data=np.genfromtxt('kmeans.txt',delimiter=' ')
k=4
1
2
3
#训练模型
model=KMeans(n_clusters=k)
model.fit(data)
KMeans(n_clusters=4)
1
2
3
centers=model.cluster_centers_
#中心点坐标
centers
array([[-3.38237045, -2.9473363 ],
       [ 2.6265299 ,  3.10868015],
       [ 2.80293085, -2.7315146 ],
       [-2.46154315,  2.78737555]])
1
2
3
#预测结果
result=model.predict(data)
result
array([1, 3, 2, 0, 1, 3, 2, 0, 1, 3, 2, 0, 1, 3, 2, 0, 1, 3, 2, 0, 1, 3,
       2, 0, 1, 3, 2, 0, 1, 3, 2, 0, 1, 3, 2, 0, 1, 3, 2, 0, 1, 3, 2, 0,
       1, 3, 2, 0, 1, 3, 2, 0, 1, 3, 2, 0, 1, 3, 2, 0, 1, 3, 2, 0, 1, 3,
       2, 0, 1, 3, 2, 0, 1, 3, 2, 0, 1, 3, 2, 0])
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 获取数据值所在的范围
x_min, x_max = data[:, 0].min() - 1, data[:, 0].max() + 1
y_min, y_max = data[:, 1].min() - 1, data[:, 1].max() + 1

# 生成网格矩阵
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.02),
np.arange(y_min, y_max, 0.02))

z = model.predict(np.c_[xx.ravel(), yy.ravel()])# ravel与flatten类似,多维数据转一维。flatten不会改变原始数据,ravel会改变原始数据
z=z.reshape(xx.shape)
cs=plt.contourf(xx,yy,z)

mark = ['or', 'ob', 'og', 'ok', '^r', '+r', 'sr', 'dr', '<r', 'pr']
for i in range(data.shape[0]):

plt.plot(data[i, 0], data[i, 1], mark[result[i]])

# 用不同颜色形状来表示各个类别
mark = ['*r', '*b', '*g', '*k', '^b', '+b', 'sb', 'db', '<b', 'pb']
# 画质心点
for i in range(k):
plt.plot(centers[i, 0], centers[i, 1], mark[i], markersize = 20)

plt.show()

png

2.Mini Batch K-Means

Mini Batch K-Means 算法是K—Means算法的变种,采用小批量的数据子集减小计算时间。这里的小批量是指每次训练算法时所随机抽取的数据子集,采用这些随机产生的子集进行训练,大大减少了计算时间,结果一般只略差与标准算法。
该算法的迭代步骤有两步:
1.从数据集中随机抽取一些数据形成小批量,把他们分配给更近的重心
2.更新重心
Mini Batch K-Means比K-Means 相比有更快的收敛速度,但同时也降低了聚类效果

sklearn实现
1
from sklearn.cluster import MiniBatchKMeans
1
2
3
data=np.genfromtxt('kmeans.txt',delimiter=' ')
model1=MiniBatchKMeans(n_clusters=4)
model1.fit(data)
MiniBatchKMeans(n_clusters=4)
1
2
centers1=model1.cluster_centers_
centers1
array([[-3.35355922, -2.94580235],
       [-2.38894596,  2.82134059],
       [ 2.79165315, -2.79705023],
       [ 2.61970115,  3.11412341]])
1
2
result1=model1.predict(data)
print(result1)
[3 1 2 0 3 1 2 0 3 1 2 0 3 1 2 0 3 1 2 0 3 1 2 0 3 1 2 0 3 1 2 0 3 1 2 0 3
 1 2 0 3 1 2 0 3 1 2 0 3 1 2 0 3 1 2 0 3 1 2 0 3 1 2 0 3 1 2 0 3 1 2 0 3 1
 2 0 3 1 2 0]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 获取数据值所在的范围
x_min, x_max = data[:, 0].min() - 1, data[:, 0].max() + 1
y_min, y_max = data[:, 1].min() - 1, data[:, 1].max() + 1

# 生成网格矩阵
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.02),
np.arange(y_min, y_max, 0.02))

z = model1.predict(np.c_[xx.ravel(), yy.ravel()])# ravel与flatten类似,多维数据转一维。flatten不会改变原始数据,ravel会改变原始数据
z=z.reshape(xx.shape)
cs=plt.contourf(xx,yy,z)

mark = ['or', 'ob', 'og', 'ok', '^r', '+r', 'sr', 'dr', '<r', 'pr']
for i in range(data.shape[0]):

plt.plot(data[i, 0], data[i, 1], mark[result1[i]])

# 用不同颜色形状来表示各个类别
mark = ['*r', '*b', '*g', '*k', '^b', '+b', 'sb', 'db', '<b', 'pb']
# 画质心点
for i in range(k):
plt.plot(centers1[i, 0], centers1[i, 1], mark[i], markersize = 20)

plt.show()

png

3.K-Means 算法问题

1.对于K个初始质心的选择比较敏感,容易陷入局部最小值

对于K个初始质心的选择比较敏感,容易陷入局部最小值。
例如在运行K-Means的程序中,每次运行结果可能都不一样,如下面的两种情况,K-Means也是收敛了,但只是收敛到了局部最小值
在这里插入图片描述
解决办法:
使用多次的随机初始化,计算每一次建模得到的代价函数的值,选取代价函数最小的结果最为聚类结果。
在这里插入图片描述
x表示样本,u表示x对应得簇得重心。

1
2
import numpy as np
import matplotlib.pylab as plt
1
2
3
data=np.genfromtxt('kmeans.txt',delimiter=' ')
print(data.shape)
print(data[:5,:])
(80, 2)
[[ 1.658985  4.285136]
 [-3.453687  3.424321]
 [ 4.838138 -1.151539]
 [-5.379713 -3.362104]
 [ 0.972564  2.924086]]
1
2
def eucldistance(v1,v2):#计算距离
return np.sqrt(sum((v2-v1)**2))
1
2
3
4
5
6
7
8
9
10
11
12
13
def initCenter(data,k):
numSanples,dim=data.shape
#获取样本行数和列数

center=np.zeros((k,dim))
#生成k个重心

for i in range(k):
index=int(np.random.uniform(0,numSanples))
#从0-79中随机选择一个索引
center[i,:]=data[index,:]
#初始化重心
return center
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
def kmeans(data,k):
numSamples=data.shape[0]#样本个数
#样本的属性,第一列表示它属于哪个簇,第二列表示它与该簇的误差(到重心的距离)
resultData=np.array(np.zeros((numSamples,2)))

isChange=True #聚类是否发生了改变

center=initCenter(data,k)
#初始化重心

while (isChange):
isChange=False

#对每个样本进行循环,计算器属于那个类别
for i in range(numSamples):
Mindist=10000
minindex=0
#先给一个很大的距离

for j in range(k):
distance=eucldistance(center[j,:],data[i,:])
#循环计算每一个样本点到每一个重心的距离

#如果计算出的距离小于当前最小距离,则对最小距离进行更新
if(distance<Mindist):
Mindist=distance
resultData[i,1]=distance
minindex=j#更新样本的簇

if resultData[i,0] !=minindex:#样本的簇发生了改变,需要继续更新
isChange=True#质心要重新计算
resultData[i,0]=minindex#更新样本的簇

for j in range(k):
# 获取第j个簇所有的样本所在的索引
cluster_index=np.nonzero(resultData[:,0]==j)
point=data[cluster_index]
#提取出第j簇的所有样本点
center[j,:]=np.mean(point,axis=0)
return center,resultData
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 显示结果 
def showCluster(data, k, centroids, resultData):
numSamples, dim = data.shape
if dim != 2:
print("dimension of your data is not 2!")
return 1

# 用不同颜色形状来表示各个类别
mark = ['or', 'ob', 'og', 'ok', '^r', '+r', 'sr', 'dr', '<r', 'pr']
if k > len(mark):
print("Your k is too large!")
return 1

# 画样本点
for i in range(numSamples):
markIndex = int(resultData[i, 0])
plt.plot(data[i, 0], data[i, 1], mark[markIndex])

# 用不同颜色形状来表示各个类别
mark = ['*r', '*b', '*g', '*k', '^b', '+b', 'sb', 'db', '<b', 'pb']
# 画质心点
for i in range(k):
plt.plot(centroids[i, 0], centroids[i, 1], mark[i], markersize = 20)

plt.show()
1
2
3
#做预测
def predict(datas):
return np.array([np.argmin(((np.tile(data,(k,1))-center)**2).sum(axis=1)) for data in datas])
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
k=4

min_loss=10000
min_loss_center=np.array([])
min_loss_result=np.array([])

for i in range(50):
center,resultData=kmeans(data,k)
loss=sum(resultData[:,1])/data.shape[0]

if loss<min_loss:
min_loss=loss
min_loss_center=center
min_loss_result=resultData

center=min_loss_center
resultData=min_loss_result
showCluster(data,k,center,resultData)

png

1
2
3
4
5
6
7
8
9
10
11
12
# 获取数据值所在的范围
x_min, x_max = data[:, 0].min() - 1, data[:, 0].max() + 1
y_min, y_max = data[:, 1].min() - 1, data[:, 1].max() + 1

# 生成网格矩阵
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.02),
np.arange(y_min, y_max, 0.02))

z = predict(np.c_[xx.ravel(), yy.ravel()])# ravel与flatten类似,多维数据转一维。flatten不会改变原始数据,ravel会改变原始数据
z=z.reshape(xx.shape)
cs=plt.contourf(xx,yy,z)
showCluster(data,k,center,resultData)

png

在经过多次循环取得损失最小时对应的重心和结果时,多次运行聚类的结果明显比较稳定了许多

2.K值选取是由用户决定的,不同k值得到的结果会有很大的不同

在这里插入图片描述
解决办法:肘部法则
在这里插入图片描述
若图像中没有肘部点,需要自己根据需要来设置

1
2
3
import numpy as np
import matplotlib.pylab as plt
data=np.genfromtxt('kmeans.txt',delimiter=' ')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
def eucldistance(v1,v2):#计算距离
return np.sqrt(sum((v2-v1)**2))
def initCenter(data,k):
numSanples,dim=data.shape
#获取样本行数和列数

center=np.zeros((k,dim))
#生成k个重心

for i in range(k):
index=int(np.random.uniform(0,numSanples))
#从0-79中随机选择一个索引
center[i,:]=data[index,:]
#初始化重心
return center
def kmeans(data,k):
numSamples=data.shape[0]#样本个数
#样本的属性,第一列表示它属于哪个簇,第二列表示它与该簇的误差(到重心的距离)
resultData=np.array(np.zeros((numSamples,2)))

isChange=True #聚类是否发生了改变

center=initCenter(data,k)
#初始化重心

while (isChange):
isChange=False

#对每个样本进行循环,计算器属于那个类别
for i in range(numSamples):
Mindist=10000
minindex=0
#先给一个很大的距离

for j in range(k):
distance=eucldistance(center[j,:],data[i,:])
#循环计算每一个样本点到每一个重心的距离

#如果计算出的距离小于当前最小距离,则对最小距离进行更新
if(distance<Mindist):
Mindist=distance
resultData[i,1]=distance
minindex=j#更新样本的簇

if resultData[i,0] !=minindex:#样本的簇发生了改变,需要继续更新
isChange=True#质心要重新计算
resultData[i,0]=minindex#更新样本的簇

for j in range(k):
# 获取第j个簇所有的样本所在的索引
cluster_index=np.nonzero(resultData[:,0]==j)
point=data[cluster_index]
#提取出第j簇的所有样本点
center[j,:]=np.mean(point,axis=0)
return center,resultData
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 显示结果 
def showCluster(data, k, centroids, resultData):
numSamples, dim = data.shape
if dim != 2:
print("dimension of your data is not 2!")
return 1

# 用不同颜色形状来表示各个类别
mark = ['or', 'ob', 'og', 'ok', '^r', '+r', 'sr', 'dr', '<r', 'pr']
if k > len(mark):
print("Your k is too large!")
return 1

# 画样本点
for i in range(numSamples):
markIndex = int(resultData[i, 0])
plt.plot(data[i, 0], data[i, 1], mark[markIndex])

# 用不同颜色形状来表示各个类别
mark = ['*r', '*b', '*g', '*k', '^b', '+b', 'sb', 'db', '<b', 'pb']
# 画质心点
for i in range(k):
plt.plot(centroids[i, 0], centroids[i, 1], mark[i], markersize = 20)

plt.show()

#做预测
def predict(datas):
return np.array([np.argmin(((np.tile(data,(k,1))-center)**2).sum(axis=1)) for data in datas])
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
list_lost=[]
for k in range(2,10):
min_loss=10000
min_loss_center=np.array([])
min_loss_result=np.array([])

for i in range(50):
center,resultData=kmeans(data,k)
loss=sum(resultData[:,1])/data.shape[0]

if loss<min_loss:
min_loss=loss
min_loss_center=center
min_loss_result=resultData
list_lost.append(min_loss)
1
list_lost
[2.9811811738953176,
 1.9708559728104191,
 1.1675654672086735,
 1.0712368269135584,
 1.0064227003008,
 0.9383457643136094,
 0.8888370860975188,
 0.8447057982645164]
1
2
3
4
plt.plot(range(2,10),list_lost)
plt.xlabel('k')
plt.ylabel('loss')
plt.show()

png

从图中可以明显看出k=4时就是其肘部点,将该样本数据聚成4类较为合理

3.存在局限性

在这里插入图片描述
解决办法:DBSCAN算法

4.数据比较大的时候,收敛会比较慢

解决办法:mini batch k-means

4.DBSCan算法

DBSCAN算法算法是基于密度得一类聚类算法,可以将具有足够高密度的区域划分成簇,并可以发现任何形状的聚类。
下面先介绍几组概念:
==ϵ\epsilon邻域==:给定对象半径ϵ\epsilon内的区域称为该对象的ϵ\epsilon邻域。
如下图所示,如果假设p点为中心点,以ϵ\epsilon为半径的圆域就是p的ϵ\epsilon邻域。
==核心对象==:如果给定ϵ\epsilon邻域内的样本点数大于等于Minpoints,则该对象为核心对象。
如下图:假设Minpoints=3,以p为中心,他的ϵ\epsilon邻域内有4个样本点,大于Minpoints,所以以p为中心的ϵ\epsilon邻域是核心对象,而以Q为中心的ϵ\epsilon邻域中只有2个样本点,所以不是核心对象。
==直接密度可达==:给定一个对象集合D,如果q在p的ϵ\epsilon邻域内,且q是一个核心对象,则我们说对象p是从q出发是直接密度可达的。
如下图,如果p点是一个核心对象,M点是在P的ϵ\epsilon邻域内,那么认为M从P出发是直接密度可达的。
==密度可达==:集合D,存在一个对象链p1,p2,……,pn,满足p1=q,pn=p,且pn+1由pn直接密度可达,则称p由q密度可达。也就是说密度可达具有传递性。
如下图,P到M是直接密度可达的,M到Q也是直接密度可达的,那么P到Q就是密度可达的。
==密度相连==:集合D中存在点o,使得点p,q是从o关于ϵ\epsilon和Minpoints密度可达的,那么p,q是关于ϵ\epsilon和minpoint是密度相连的。
如下图,O到R是密度可达的,O到S也是密度可达的,则成S和R是密度相连的。

在这里插入图片描述

算法思想

1.指定合适的ϵ\epsilon和minpoints
2.计算所有的样本的,如果点p的ϵ\epsilon邻域里由超过Minpoints个点,则创建一个以p为核心点的新簇。
3.反复寻找这些核心点直接密度可达的点,将其加入到相应的簇,对于核心点发生“密度相连”状况的簇,给与合并。
4,当没有新的点可以被添加到任何簇时,算法结束。

算法优缺点:
优点:
①可以对任意形状的数据集进行聚类。
②可以在聚类的同时发现异常点,对数据集中的异常点不敏感。
③聚类结果较为稳定,相对的,k——Means算法初始值对聚类结果有很大的影响。
缺点:
①当数据量增大时,要求较大的内存支持和I/O消耗。
②当空间聚类的密度不均匀,聚类间差距差相差很大时,聚类质量较差。
DBSCAN与K-Means比较:
DBSCAN不需要输入聚类个数。
聚类的形状没有要求。
可以在需要时输入过滤噪声的参数(ϵ\epsilon和minpoints)

算法可视化网站,有兴趣可以去玩一玩。

sklearn实现
1
2
3
from sklearn.cluster import DBSCAN
import numpy as np
import matplotlib.pyplot as plt
1
2
#载入数据
data=np.genfromtxt('kmeans.txt',delimiter=' ')
1
2
3
4
#训练模型
model=DBSCAN(eps=1.5,min_samples=4)
#eps时邻域的半径 min——samples是称为核心对象最小样本数
model.fit(data)
DBSCAN(eps=1.5, min_samples=4)
1
2
3
result=model.fit_predict(data)#先Fit后predict
result
#样本标签为-1表示不属于任何一个类别
array([ 0,  1,  2,  3,  0,  1,  2,  3,  0,  1,  2,  3,  0,  1, -1,  2,  0,
        1,  2,  3,  0,  1,  2,  3,  0,  1,  2,  3,  0,  1,  2,  3,  0,  1,
        2,  3,  0,  1,  2,  3,  0,  1,  2,  3,  0,  1,  2,  3,  0,  1,  2,
        3,  0,  1,  2,  3,  0,  1,  2,  3,  0,  1,  2,  3,  0,  1,  2,  3,
        0,  1,  2,  3,  0,  1,  2,  3,  0,  1,  2,  3], dtype=int64)
1
2
3
4
5
6
#画出各个数据点,用不同颜色分类表示
mark=['or','ob','og','oy','ok','om']
for i ,d in enumerate(data):
plt.plot(d[0],d[1],mark[result[i]])
plt.show()
#紫色点可以认为是噪音数据

在这里插入图片描述