聚类kmeans和DBSCAN算法的简单实现

简介: 笔记

在无监督学习中,我们首先就会接触到kmeans算法,因为既简单,又实用,而且速度也很快。所以今天在这里写一个非常简单的kmeans算法,以帮助我们更快的领悟算法的思想,以及它的变种。一下是其实现步骤


1.确定聚类数,数据分为多少类。

2.随机初始化每一类的中心点。

3.计算每一个样本点到每一类中心点的距离,并分配给距离它最小的那个中心点。

4.更新中心点,新的中心点为属于它所有点的平均值。

5.重复3,4操作,即可完成。

数据不是太漂亮,实现的效果也不是特别好,代码写的很简单,还有优化的空间。

from sklearn.datasets import load_iris
import numpy as np
import matplotlib.pyplot as plt
a,b = load_iris(return_X_y=True)
x = a[:,:2]   #便于绘图
center_1 = np.array([5,3.5])   #初始化中心点
center_2 = np.array([6,2]) 
center_3 = np.array([7,3])
for k in range(200):
    center_list1 = []
    center_list2 = []
    center_list3 = []
    for i in x:
        a = ((i[0] - center_1[0])*(i[1]-center_1[1]))**2
        b = ((i[0] - center_2[0])*(i[1]-center_2[1]))**2
        c = ((i[0] - center_3[0])*(i[1]-center_3[1]))**2
        if a<b and a<c :
            center_list1.append(i)
        elif b<c:
            center_list2.append(i)
        elif c<b :
            center_list3.append(i)
    new_1_x =  0
    new_1_y = 0
    for a in center_list1:
        new_1_x +=a[0]
        new_1_y +=a[1]
    center_1[0] = new_1_x / (len(center_list1))
    center_1[1] = new_1_y / (len(center_list1))
    new_1_x = 0
    new_1_y = 0
    for a in center_list2:
        new_1_x += a[0]
        new_1_y += a[1]
    print(len(center_list3))
    center_2[0] = new_1_x / (len(center_list2))
    center_2[1] = new_1_y / (len(center_list2))
    new_1_x = 0
    new_1_y = 0
    for a in center_list3:
        new_1_x += a[0]
        new_1_y += a[1]
    center_3[0] = new_1_x / (len(center_list3))
    center_3[1] = new_1_y / (len(center_list3))
plt.scatter([x[0] for x in center_list1],[x[1] for x in center_list1],c='red')
plt.scatter([x[0] for x in center_list2],[x[1] for x in center_list2],c='green')
plt.scatter([x[0] for x in center_list3],[x[1] for x in center_list3],c='blue')
plt.scatter(center_1[0],center_1[1],c='black')
plt.scatter(center_2[0],center_2[1],c = 'black')
plt.scatter(center_3[0],center_3[1],c='black')
plt.show()

3.png

下面的这个代码是一个优化的版本,参考于https://www.cnblogs.com/zxzhu/p/7994612.html

该博客主写的方法也太简单的,便于阅读,很适合学习。

 1
 2
 3
 4
 5
 6 from sklearn.datasets import make_blobs
 7 import numpy as np
 8 import matplotlib.pyplot as plt
 9 
10 
11 def Distance(x):
12     def Dis(y):
13         return np.sqrt(sum((x-y)**2))                      #欧式距离
14     return Dis
15 
16 def init_k_means(k):
17     k_means = {}
18     for i in range(k):
19         k_means[i] = []
20     return k_means
21 
22 def cal_seed(k_mean):                                      #重新计算种子点
23     k_mean = np.array(k_mean)
24     new_seed = np.mean(k_mean,axis=0)                      #各维度均值
25     return new_seed
26     
27 def K_means(data,seed_k,k_means):
28     for i in data:
29         f = Distance(i)
30         dis = list(map(f,seed_k))                 #某一点距所有中心点的距离
31         index = dis.index(min(dis))
32         k_means[index].append(i)
33     
34     new_seed = []                                         #新的样本中心点
35     for i in range(len(seed_k)):
36         new_seed.append(cal_seed(k_means[i]))
37     new_seed = np.array(new_seed)
38     return k_means,new_seed
39     
40 def run_K_means(data,k):
41     seed_k = data[np.random.randint(len(data),size=k)]    #随机产生样本中心点
42     k_means = init_k_means(k)                             #初始化每一类
43     result = K_means(data,seed_k,k_means)
44     count = 0
45     while not (result[1] == seed_k).all():            #种子点改变,继续聚类
46         count+=1
47         seed_k = result[1]
48         k_means = init_k_means(k=7)   
49         result = K_means(data,seed_k,k_means)
50     print('Done')
51     #print(result[1])
52     print(count)
53     plt.figure(figsize=(8,8))
54     Color = 'rbgyckm'
55     for i in range(k):
56         mydata = np.array(result[0][i])
57         plt.scatter(mydata[:,0],mydata[:,1],color = Color[i])
58     return result[0]
59 x,y = make_blobs(n_features=3,n_samples=1000,random_state=21)
60 
61 run_K_means(data,k=3)   

程序中那个闭包的操作需要我们多去捋一捋。


在聚类中使用的较多的一种聚类是基于密度的DBSCAN算法,该算法不需要指定类别数,但是要指定半径大小以及该范围内包含点的最小数目。


DBSCAN算法描述:输入:

输入: 包含n个对象的数据库,半径e,最少数目MinPts;

输出:所有生成的簇,达到密度要求。

(1)Repeat

(2)从数据库中抽出一个未处理的点;

(3)IF抽出的点是核心点 THEN 找出所有从该点密度可达的对象,形成一个簇;

(4)ELSE 抽出的点是边缘点(非核心对象),跳出本次循环,寻找下一个点;

(5)UNTIL 所有的点都被处理。

DBSCAN对用户定义的参数很敏感,细微的不同都可能导致差别很大的结果,而参数的选择无规律可循,只能靠经验确定。


1.与K-means方法相比,DBSCAN不需要事先知道要形成的簇类的数量。

2.与K-means方法相比,DBSCAN可以发现任意形状的簇类。

3.同时,DBSCAN能够识别出噪声点。

4.DBSCAN对于数据库中样本的顺序不敏感,即Pattern的输入顺序对结果的影响不大。但是,对于处于簇类之间边界样本,可能会根据哪个簇类优先被探测到而>其归属有所摆动。


具体的实现如下,过程很简单,细读后,复现应该是没有问题的,我也是从

https://www.cnblogs.com/tiaozistudy/p/dbscan_algorithm.html,里面学来的,代码基本一样,他里面有跟详细的介绍。

import math
import numpy as np
from sklearn.datasets import make_circles
import random
import matplotlib.pyplot as plt
class visited:
'''
  记录那些点是被标记了的,那些点是没有被标记的,以及没有被标记点的个数  , 记录的是每个点在data里面的位置,也就是index
'''
  def __init__(self,count=0):
    self.visitedlist = list()
    self.unvisitedlist = [i for i in range(count]
    self.unvisitednum = count
  def visvit(self,opints):
    self.visitedlist.append(opints)
    self.unvisitedlist.remove(opints)
    self.unvisitednum -= 1
#计算距离
def dist(x , y):
  return math.sqrt(np.power(x-y,2).sum())
def DBSCAN(data,eps,minpts):
  count = data.shape[0]
  visit = visited(count)
  k = -1   #表示类别
  C = [-1 for i in range(count]
  while (visit.unvisitednum > 0 ):
    p = random.choice(visit.unvisitedlist)   
    visit.visvit(p)
    N = [i for i in visit.unvisitedlist if dist(data[i],data[p]) <= eps]
    if len(N) >= minpts:
      k += 1
      C[p] = k
      for p1 in N:
        visit.visvit(p1)
        M = [i for i in visit.unvisitedlist if dist(data[i],data[p]) <= eps]
        if len(M) >=minpts:
          for i in M:
            if i not in N:
              N.append(i)
        C[p1] = k
    else:
      C[p] = -1
  return C
x ,y = make_circles(n_samples=2000,factor=0.6,noise=0.05,random_state=1)
a = DBSCAN(x,0.1,10)
plt.figure(figsize=(12,9))
plt.scatter(x[:,0],x[:,1],c = a)
plt.show()

上面讲述了两种常用的聚类方法,里面的DBSCAN还可以用KD树来优化,这里就不讲述了,(我也不会)。聚类方法也还挺简单的,没有那些复杂的数学公式推导,相信你们也和我一样,看到公式就头疼。聚类的算法重点还是其思想,理解了它的思想,那么你也就成功了65%。

公众号:FPGA之旅


目录
相关文章
|
2月前
|
机器学习/深度学习 算法 数据挖掘
K-means聚类算法是机器学习中常用的一种聚类方法,通过将数据集划分为K个簇来简化数据结构
K-means聚类算法是机器学习中常用的一种聚类方法,通过将数据集划分为K个簇来简化数据结构。本文介绍了K-means算法的基本原理,包括初始化、数据点分配与簇中心更新等步骤,以及如何在Python中实现该算法,最后讨论了其优缺点及应用场景。
117 4
|
5月前
|
数据采集 机器学习/深度学习 算法
【优秀设计案例】基于K-Means聚类算法的球员数据聚类分析设计与实现
本文通过K-Means聚类算法对NBA球员数据进行聚类分析,旨在揭示球员间的相似性和差异性,为球队管理、战术决策和球员评估提供数据支持,并通过特征工程和结果可视化深入理解球员表现和潜力。
184 1
【优秀设计案例】基于K-Means聚类算法的球员数据聚类分析设计与实现
|
2月前
|
算法 数据挖掘 数据安全/隐私保护
基于FCM模糊聚类算法的图像分割matlab仿真
本项目展示了基于模糊C均值(FCM)算法的图像分割技术。算法运行效果良好,无水印。使用MATLAB 2022a开发,提供完整代码及中文注释,附带操作步骤视频。FCM算法通过隶属度矩阵和聚类中心矩阵实现图像分割,适用于灰度和彩色图像,广泛应用于医学影像、遥感图像等领域。
|
3月前
|
算法 数据挖掘
基于粒子群优化算法的图象聚类识别matlab仿真
该程序基于粒子群优化(PSO)算法实现图像聚类识别,能识别0~9的数字图片。在MATLAB2017B环境下运行,通过特征提取、PSO优化找到最佳聚类中心,提高识别准确性。PSO模拟鸟群捕食行为,通过粒子间的协作优化搜索过程。程序包括图片读取、特征提取、聚类分析及结果展示等步骤,实现了高效的图像识别。
|
5月前
|
人工智能 算法 数据可视化
DBSCAN密度聚类算法(理论+图解+python代码)
DBSCAN密度聚类算法(理论+图解+python代码)
|
5月前
|
算法 数据可视化 搜索推荐
基于python的k-means聚类分析算法,对文本、数据等进行聚类,有轮廓系数和手肘法检验
本文详细介绍了基于Python实现的k-means聚类分析算法,包括数据准备、预处理、标准化、聚类数目确定、聚类分析、降维可视化以及结果输出的完整流程,并应用该算法对文本数据进行聚类分析,展示了轮廓系数法和手肘法检验确定最佳聚类数目的方法。
130 0
|
9天前
|
机器学习/深度学习 算法
基于改进遗传优化的BP神经网络金融序列预测算法matlab仿真
本项目基于改进遗传优化的BP神经网络进行金融序列预测,使用MATLAB2022A实现。通过对比BP神经网络、遗传优化BP神经网络及改进遗传优化BP神经网络,展示了三者的误差和预测曲线差异。核心程序结合遗传算法(GA)与BP神经网络,利用GA优化BP网络的初始权重和阈值,提高预测精度。GA通过选择、交叉、变异操作迭代优化,防止局部收敛,增强模型对金融市场复杂性和不确定性的适应能力。
143 80
|
3天前
|
机器学习/深度学习 算法
基于遗传优化的双BP神经网络金融序列预测算法matlab仿真
本项目基于遗传优化的双BP神经网络实现金融序列预测,使用MATLAB2022A进行仿真。算法通过两个初始学习率不同的BP神经网络(e1, e2)协同工作,结合遗传算法优化,提高预测精度。实验展示了三个算法的误差对比结果,验证了该方法的有效性。
|
5天前
|
机器学习/深度学习 数据采集 算法
基于PSO粒子群优化的CNN-GRU-SAM网络时间序列回归预测算法matlab仿真
本项目展示了基于PSO优化的CNN-GRU-SAM网络在时间序列预测中的应用。算法通过卷积层、GRU层、自注意力机制层提取特征,结合粒子群优化提升预测准确性。完整程序运行效果无水印,提供Matlab2022a版本代码,含详细中文注释和操作视频。适用于金融市场、气象预报等领域,有效处理非线性数据,提高预测稳定性和效率。
|
2天前
|
算法
基于梯度流的扩散映射卡尔曼滤波算法的信号预处理matlab仿真
本项目基于梯度流的扩散映射卡尔曼滤波算法(GFDMKF),用于信号预处理的MATLAB仿真。通过设置不同噪声大小,测试滤波效果。核心代码实现数据加载、含噪信号生成、扩散映射构建及DMK滤波器应用,并展示含噪与无噪信号及滤波结果的对比图。GFDMKF结合非线性流形学习与经典卡尔曼滤波,提高对非线性高维信号的滤波和跟踪性能。 **主要步骤:** 1. 加载数据并生成含噪测量值。 2. 使用扩散映射捕捉低维流形结构。 3. 应用DMK滤波器进行状态估计。 4. 绘制不同SNR下的轨迹示例。

热门文章

最新文章