C-Means(C均值)模糊聚类和最大最小距离法

本文介绍了鸢尾花数据集及其在分类中的应用,详细阐述了C-Means(包括模糊C均值FCM)聚类算法的基本原理和流程,并对比了最大最小距离(MMD)算法。通过实验展示了C-Means的实现过程,包括初始类中心的选择、迭代次数、聚类结果和错误率。实验结果显示,模糊C均值算法在分类准确性上有优势。
摘要由CSDN通过智能技术生成

1. 基础知识

1.1 IRIS数据集介绍

Iris数据集是常用的分类实验数据集,由Fisher于1936年完成收集整理。IRIS也称鸢尾花卉数据集,是一类多重变量分析的数据集。数据集总共包含150个数据样本,共分为三类,每类各有50个数据,且每个数据包含4个属性。可通过花萼长度、花萼宽度、花瓣长度、花瓣宽度共四个属性预测鸢尾花卉属于(Setosa,Versicloour,Virginica)三个种类中的哪一类。常用在分类操作中。其中的一个种类与另外两个种类是线性可分离的,后两个种类是非线性可分离的。该数据共包含了四个属性:

  • & Sepal Length(花萼长度),单位:cm(厘米);
  • & Sepal Width(f花萼宽度), 单位:cm(厘米);
  • & Petal Length(花瓣长度),单位:cm(厘米);
  • & Petal Width(花瓣宽度), 单位:cm(厘米);
  • 种类:Iris Setosa(山鸢尾)
  • Iris Versicolour(杂色鸢尾)
  • Iris Virginica(维吉尼亚鸢尾)

1.2 C-Means(C均值)模糊聚类

核心思想:C-mean均值聚类是典型的一种动态聚类算法,其基本思想是在每次迭代时,每个样本归为与之距离最近的那个聚类中心所属的类,f全部归类完成后,重新计算新的聚类中心;然后接着重复之前的步骤,直到聚类中心不再发生变化,则聚类完成。
模糊聚类算法是一种基于函数最优方法的聚类算法,使用微积分计算技术求最优代价函数.在基于概率算法的聚类方法中将使用概率密度函数,为此要假定合适的模型.模糊聚类算法中向量可以同时属于多个聚类,从而摆脱上述问题.在模糊聚类算法中,定义了向量与聚类之间的近邻函数,并且聚类中向量的隶属度由隶属函数集合提供.对模糊方法而言,在不同聚类中的向量隶属函数值是相互关联的.硬聚类可以看成是模糊聚类方法的一个特例。
FCM算法是一种基于划分的聚类算法,它的思想就是使得被划分到同一簇的对象之间相似度最大,而不同簇之间的相似度最小。模糊C均值算法是普通C均值算法的改进,普通C均值算法对于数据的划分是硬性的,而FCM则是一种柔性的模糊划分。
普通C-Means(C均值)(即K-Means/K均值)算法在分类时有一个硬性标准,根据该标准进行划分,分类结果非此即彼。模糊C均值算法更看重隶属度,即更接近于哪一方,隶属度越高,其相似度越高。由以上叙述不难判断,用模糊C均值算法来进行组类划分会使结果更加准确!
其中涉及的公式如下:

隶属矩阵:(1)
聚类中心:(2)
目标函数:(3)
约束条件:(4)

FCM聚类算法流程:
![image.png](https://img-blog.csdnimg.cn/img_convert/805be3eb6a1812b2b65327d9cae15e41.png#clientId=u9bdb41ca-c7dc-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=334&id=u4fec7483&margin=[object Object]&name=image.png&originHeight=540&originWidth=419&originalType=binary&ratio=1&rotation=0&showTitle=false&size=32381&status=done&style=none&taskId=u014508bc-9c09-48fb-920e-b3ecd282b49&title=&width=259.5)
图1.1 FCM聚类算法的流程图
(注:初始化时,取模糊加权指数m=2,设定聚类数目c,设定迭代停止阈值,一般取0.001,初始聚类中心值,设置迭代计数器,最大迭代次数。)
C-Means算法步骤:

  1. 用值在0,1间的随机数初始化隶属矩阵,使其满足(1)中的约束条件。
  2. 用式(3)计算个聚类中心。
  3. 根据式(2)计算价值函数。如果他小于某个确定的值,或他相对于上次价值函数值的改变量小于某个阈值,则算法停止。
  4. 用式(4)计算新的隶属矩阵。返回步骤2。

上述算法也可以先初始化聚类中心,然后再执行迭代过程。由于算法的性能依赖于初始聚类中心。因此,我们要么用另外的快速算法来确定初始聚类中心,要么每次用不同的初始聚类中心启动该算法,多次运行FCM,使结果不断接近目标函数。
FCM与普通分类的区别就在于FCM用模糊划分,使得每个给定数据点用值域在0到1之间的隶属度函数确定其属于各个类的程度以达到分类的目的。

1.3 MMD(最大最小距离)分类

最大最小距离算法是模式识别中一种基于试探的聚类算法,该算法以欧几里得距离(即欧氏距离)为基础,取尽可能远的对象作为聚类中心。因此可以避免C-Means法初始值选取时可能出现的聚类种子过于临近的情况,它不仅能智能确定初始聚类种子的个数,而且提高了划分初始数据集的效率。
MMD算法步骤:

  1. 首先需要初始一个样本对象作为第一个聚类中心(即随机的)Z_1。
  2. 再选择一个与第一个聚类中心Z_1最远的样本作为第二个聚类中心Z_2。
  3. 逐个计算所有样本与已知的所有聚类中心之间的距离d,并选出其中的最小距离d_{min}。
  4. 在所有的最小距离中选出一个最大距离d_{max}。如果d_{max}>\delta,则将产生最大距离的那个样本作为新的聚类中心,并返回上一步。否则,聚类中心的计算步骤结束。
  5. 重复步骤3和4,直到没有新的聚类中心产生。
  6. 最后将样本按照最小距离的原则归入最近的类。
    从上面的步骤可以看出,最大最小距离算法可以概括的描述为以“试探类间欧氏距离最大”作为预选出最初聚类中心的条件;根据最小距离中的最大距离情况,确定其余的聚类中心;将全部聚类中心确定完之后,再按最近距离将所有模式划分到各类中去。算法的关键是怎样开新类,以及新类中心如何确定。因为算法的核心是寻找最小距离中的最大距离,所以也称小中取大距离算法。

2. 实验要求

2.1 C-Means的实验要求

① 要求给出以下数据:初始类中心点;迭代次数;聚类结果(每类包含的样本、类中心);错误率。
② 建议用最大最小距离方法选定初始类中心点,并与其他选择初始点的方法进行比较。

2.2 最大最小距离法的实验要求

① 要求给出阈值t,最后聚类结果等。

3. 代码分析及结果

3.1 C-Means代码实现

#引入数据集,sklearn包含众多数据集
from sklearn import datasets
from sklearn import preprocessing
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt

#引入数据,本次导入鸢尾花数据,iris数据包含4个特征变量
train_data, train_target = datasets.load_iris(return_X_y=True)
print('特征值数据格式:' , train_data.shape, '目标值数据格式:', train_target.shape)
print('目标label=\n',train_target)
plt.figure(1)
plt.scatter(train_data[:,0],train_data[:,2], c=train_target)
plt.title('KMeans clustering resourse')
plt.xlabel('x')
plt.ylabel('y')

#数据预处理
preprocessing.minmax_scale(train_data)
k_means = KMeans(n_clusters=3, init='k-means++').fit(train_data)
#print(k_means.score(X_train,y_train))
label = k_means.labels_
Centroids = k_means.cluster_centers_  # 查看质心
Inertia = k_means.inertia_  # 每个簇内到其质心的距离和,越小越相似
#计算该算法的错误率
num=0
for i in range(0,50):
if(label[i]==0):
num+=1
for i in range(50,100):
if (label[i] == 1):
num += 1
for i in range(100,150):
if (label[i] == 2):
num += 1
rate = 1 - num/150
#打印实验所要求的各个参数
print('K-Means的label=\n',label)
print('K-Means的质心=\n',Centroids)
print('K-Means的各个点到中心点的距离=\n',Inertia)
print('K-Means的错误率=\n',rate)
#绘制聚类图
plt.figure(2)
plt.clf()
colours = ['g', 'r', 'b', 'y', 'c']
class_label = ['Class 1', 'Class 2', 'Class 3', 'center']
for i in range(3):
kmeans_members = label == i
plt.scatter(Centroids[:, 0], Centroids[:, 2], marker='x', c=[0, 1, 2])
plt.scatter(train_data[kmeans_members, 0], train_data[kmeans_members, 2], s=30, c=colours[i], marker='.')
plt.title('KMeans clustering result')
plt.xlabel('x')
plt.ylabel('y')
plt.show()

3.1.1 实验结果

![image.png](https://img-blog.csdnimg.cn/img_convert/c0160299f25b3ae56fad807931dd2960.png#clientId=u9bdb41ca-c7dc-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=300&id=ufab22a6c&margin=[object Object]&name=image.png&originHeight=337&originWidth=468&originalType=binary&ratio=1&rotation=0&showTitle=false&size=30468&status=done&style=none&taskId=u457c128d-9a38-4801-949e-2af446a0411&title=&width=416)![image.png](https://img-blog.csdnimg.cn/img_convert/fa57a1caf5807b4218b460f2e9598d7d.png#clientId=u9bdb41ca-c7dc-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=248&id=Qpzi3&margin=[object Object]&name=image.png&originHeight=344&originWidth=474&originalType=binary&ratio=1&rotation=0&showTitle=false&size=21040&status=done&style=none&taskId=u4195389e-a52b-4140-8430-aebcc6e09f7&title=&width=342.20001220703125)
图3.1 源数据散点图图3.2 分类后的散点图及分类中心

|

各类中心点,即K-Means的质心=
[[5.006      3.428      1.462      0.246     ]
[5.9016129  2.7483871  4.39354839 1.43387097]
[6.85       3.07368421 5.74210526 2.07105263]]
迭代次数: 4
聚类结果(每类包含的样本、类中心); 如上图3.1和3.2所示
错误率:
K-Means的各个点到中心点的距离=78.85144142614601
K-Means的错误率=0.10666666666666669

3.2 MMD代码实现

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import random
import math
from sklearn.cluster import KMeans
from sklearn.preprocessing import MinMaxScaler
data = []
with open('iris.bat', 'r') as f:
    while True:
        thisline = f.readline()
        if not thisline:
            break
        else:
            thisline = thisline.strip('\n')
            thisline = thisline.split('\t')
            data.append(thisline)
# 查找缺失值
def findNullVal(data):
    df = pd.DataFrame(data)
    print(df, df.shape)
    null_sum = 0  # find out whether there are some null values
    for i in range(df.shape[1]):
        null_sum += df[i].isnull().sum()
    print(null_sum)  # 打印缺失值的和
    return df
# 数据归一化
def dataProcess(df):
    data = np.array(df).astype('float')
    random.seed(0)
    X, y = data[:, 0:4], data[:, 4]
    MMS = MinMaxScaler().fit(X)
    X = MMS.transform(X)
    y.astype('int')
    return X, y
# 此时的x,y为输入的标准格式
class K_means:
    def __init__(self, x, y, theta = 0.5, iteration = 100):
    #x为训练数据,y为了计算准确率,theta为MMD阈值,iteration为迭代次数
        self.x = x
        self.y = y
        self.theta = theta
        self.center = []
        self.center_indices = []
        self.iteration = iteration
        print("完成初始化")
    def computeDis(self, x1, x2):#计算两点之间的欧式距离
        return math.sqrt(np.sum(np.square(np.array(x1) - np.array(x2))))
    def MMDInitialzation(self):#MMD算法
        self.center_indices.append(random.choice(np.arange(self.x.shape[0])))
        self.center.append(self.x[self.center_indices[0]])#选择第一个初始聚类点
        print("初始中心点0:" + str(self.center[0]))
        max_dis = -1
        max_dis_indice = None
        for i in range(self.x.shape[0]):
            temp_dis = self.computeDis(self.x[i], self.center[0])
            if temp_dis > max_dis:
                max_dis = temp_dis
                max_dis_indice = i
        self.center.append(self.x[max_dis_indice])
        self.center_indices.append(max_dis_indice)
        print("初始中心点1:" + str(self.center[1]))
        #第三个初始点选择
        disB01 = self.computeDis(self.center[0] , self.center[1])
        max_dis = -3
        max_dis_indice = None
        for i in range(self.x.shape[0]):
            disMin =  min(self.computeDis(self.x[i] , self.center[0]),self.computeDis(self.x[i] , self.center[1]))
            if disMin > max_dis:
                max_dis = disMin
                max_dis_indice = i
        if max_dis > self.theta * disB01:
            print("找到第三个点")
            self.center.append(self.x[max_dis_indice])
            self.center_indices.append(max_dis_indice)
        print("初始中心点2:" + str(self.center[2]))
        #进行聚类
        self.category = []
        for j in range(self.x.shape[0]):
            dis = list([0, 0, 0])
            for k in range(3):
                dis[k] = self.computeDis(self.x[j] , self.center[k])
            self.category.append(self.y[self.center_indices[dis.index(max(dis))]])
        # print(self.y)
        print(self.category)
        print((np.sum(self.y == self.category)) / len(self.y))
        return self.center_indices#返回的是中心点的索引
df = findNullVal(data)#返回dataFrame格式的数据,打印缺失值个数,如果有缺失值,则使用pandas进行处理:均值填充或者其他都可以
X, y = dataProcess(df)
k = K_means(X, y, 0.4, 1000)#创建K-Means类
#MMD聚类效果
next_center_indices = k.MMDInitialzation()

3.2.1 实验结果

初始中心点0: [0.22222222 0.20833333 0.33898305 0.41666667]
初始中心点1: [0.94444444 0.75 0.96610169 0.875 ]
找到第三个点
初始中心点2: [0.38888889 1. 0.08474576 0.125 ]
分类结果展示:
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
0. 0. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值