模糊C均值聚类(FCM)python

目录

一、模糊C均值聚类的原理 

python%E4%BB%A3%E7%A0%81-toc" style="margin-left:0px;">二、不使用skfuzzy的python代码

python%E4%BB%A3%E7%A0%81-toc" style="margin-left:0px;">三、 使用skfuzzy的python代码


一、模糊C均值聚类的原理 

 

python%E4%BB%A3%E7%A0%81">二、不使用skfuzzy的python代码

python">import numpy as np
import random
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False


'''初始化隶属矩阵'''
def initial_u0(n,K):
    '''
    :param n:样本数量
    :param K:簇的数量
    :return: 初始化的隶属矩阵
    '''
    u0=np.zeros((K,n))
    for i in range(K):
        for j in range(n):
            if i==0:
                u0[i][j]=random.uniform(0,1)
            elif i<K-1:
                s=0
                for k in range(i):
                    s=s+u0[k][j]
                u0[i][j]=random.uniform(0,1-s)
            else:
                s=0
                for k in range(i):
                    s=s+u0[k][j]
                u0[i][j]=1-s
    return u0


'''聚类函数'''
def Cluster(U,n):
    '''
    :param U:隶属度矩阵
    :param n: 样本数量
    :return: 聚类结果
    '''
    cluster=[]
    for i in range(n):
        A=U.T[i].tolist()
        a=A.index(max(A))
        cluster.append(int(a))
    return cluster


'''计算隶属中心矩阵'''
def center(data,U,m,n,K,dim):
    '''
    :param data:样本数据
    :param U: 隶属度矩阵
    :param m: 模糊加权参数,一般取2
    :param n: 样本数量
    :param K: 聚类数目
    :param dim: 维度
    :return: 隶属中心矩阵
    '''

    '''进行初始聚类'''
    cluster=Cluster(U,n)

    '''初始化隶属中心矩阵'''
    Z=np.zeros((K,dim))

    '''计算隶属中心矩阵'''
    #初始化
    u_x=[np.zeros((1,dim)) for i in range(K)]
    u=[0 for i in range(K)]
    #计算
    for i in range(n):
        c=cluster[i]  #类别
        u[c]=u[c]+(U[c][i])**m
        u_x[c]=u_x[c]+((U[c][i])**m)*data[i]
    for i in range(K):
        Z[i]=u_x[i]/u[i]

    '''返回隶属中心矩阵'''
    return Z


'''基于欧氏距离计算各点到聚类中心的距离矩阵'''
def distinct(data,n,dim,Z,K):
    '''
    :param data:样本数据
    :param n: 样本数量
    :param dim: 数据维度
    :param Z: 隶属中心矩阵
    :param K: 聚类数目
    :return: 基于欧氏距离的距离矩阵
    '''

    '''初始化距离矩阵'''
    D=np.zeros((K,n))

    '''计算欧式距离'''
    for i in range(K):
        for j in range(n):
            z=Z[i]   #隶属中心
            df=data[j]  #数据点
            df_z=df-z
            d=0
            for k in range(dim):
                d=d+(df_z[k])**2
            d=np.sqrt(d)
            D[i][j]=d

    '''返回距离矩阵'''
    return D


'''定义目标函数并返回目标函数值'''
def function(data,Z,n,dim,K,U,m,D):
    '''
    :param data:样本数据
    :param Z: 隶属中心矩阵
    :param n: 样本数量
    :param dim: 数据维度
    :param K: 聚类数目
    :param U: 隶属度矩阵
    :param m: 模糊加权参数
    :param D: 距离矩阵
    :return: 目标函数值
    '''

    '''初始化聚类'''
    cluster=Cluster(U,n)

    '''计算目标函数值'''
    J=0    #目标函数值
    W=[0 for i in range(K)]
    for i in range(n):
        c=cluster[i]  #聚类类别
        df=data[i]    #数据点
        z=Z[c]        #聚类中心
        d=D[c][i]     #数据点到聚类中心的距离
        u=U[c][i]     #隶属度
        W[c]=W[c]+(u**m)*(d**2)
    J=sum(W)

    '''返回目标函数值'''
    return J


'''更新隶属度矩阵'''
def update_U(data,Z,n,dim,K,D,m):
    '''
    :param data:样本数据
    :param Z: 隶属中心矩阵
    :param n: 样本数量
    :param dim: 数据维度
    :param K: 聚类数目
    :param D: 距离矩阵
    :param m: 模糊加权参数
    :return: 更新后的隶属度矩阵
    '''

    '''初始化隶属度矩阵'''
    U=np.zeros((K,n))

    '''更新隶属度矩阵'''
    for i in range(K):
        for j in range(n):
            r=0
            for k in range(K):
                r=r+(D[i][j]/D[k][j])**(2/(m-1))
            U[i][j]=1/r

    '''返回更新后的隶属度矩阵'''
    return U


'''模糊C均值聚类函数'''
def FCM(data,K,Tmax,m,error):
    '''
    :param data:样本数据
    :param K: 聚类数目
    :param Tmax: 最大迭代步数
    :param m: 模糊加权参数
    :param error: 迭代停止阈值,一般取0.001至0.01
    :return: 聚类结果
    '''

    '''样本数量'''
    n=data.shape[0]

    '''数据维度'''
    dim=data.shape[1]

    '''初始化隶属度矩阵'''
    U0=initial_u0(n,K)
    U=U0.copy()

    '''存储目标函数值'''
    J=[]

    '''循环'''
    for i in range(Tmax):
        #计算隶属中心矩阵
        Z=center(data,U,m,n,K,dim)
        #基于欧氏距离计算各点到聚类中心的距离矩阵
        D=distinct(data,n,dim,Z,K)
        #计算目标函数的值
        J.append(function(data,Z,n,dim,K,U,m,D))
        #更新隶属度矩阵
        U=update_U(data,Z,n,dim,K,D,m)
        #判断阈值
        if i!=0 and abs(J[i-1]-J[i])<=error:
            break

    '''得到聚类结果'''
    cluster=Cluster(U,n)

    '''返回聚类结果(聚类类别,聚类中心,目标函数值)'''
    return cluster,Z,J[-1]


'''主函数'''
if __name__=="__main__":

    '''随机产生400组在区间[0,1]上的二维数据'''
    data=np.array([[random.uniform(0, 1) for i in range(2)] for j in range(400)])

    '''聚类'''
    cluster,cntr,J=FCM(data,K=4,Tmax=1000,m=2,error=0.0001)

    print("聚类结果:\n{}".format(cluster))
    print("目标函数值:\n{}".format(J))


    #将数据分类
    fdata=data.tolist()
    X1=[]
    Y1=[]
    X2=[]
    Y2=[]
    X3=[]
    Y3=[]
    X4=[]
    Y4=[]
    for i in range(400):
        if cluster[i]==0:
            X1.append(fdata[i][0])
            Y1.append(fdata[i][1])
        if cluster[i]==1:
            X2.append(fdata[i][0])
            Y2.append(fdata[i][1])
        if cluster[i]==2:
            X3.append(fdata[i][0])
            Y3.append(fdata[i][1])
        if cluster[i]==3:
            X4.append(fdata[i][0])
            Y4.append(fdata[i][1])

    # 聚类图
    plt.scatter(X1, Y1, c='red', marker='o')
    plt.scatter([cntr[0][0]], [cntr[0][1]], marker='>', c="black", label='聚类中心1')
    plt.scatter(X2, Y2, c='blue', marker="o")
    plt.scatter([cntr[1][0]], [cntr[1][1]], marker='<', c="black", label="聚类中心2")
    plt.scatter(X3, Y3, c='green', marker="o")
    plt.scatter([cntr[2][0]], [cntr[2][1]], marker='^', c="black", label="聚类中心3")
    plt.scatter(X4, Y4, c='orange', marker="o")
    plt.scatter([cntr[3][0]], [cntr[3][1]], marker="D", c="black", label="聚类中心4")
    plt.legend()
    plt.xlabel("x")
    plt.ylabel("y")
    plt.title("聚类图")
    plt.show()

python%E4%BB%A3%E7%A0%81">三、 使用skfuzzy的python代码

python">import numpy as np
import random
import skfuzzy as fuzz
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False


'''随机产生400组在区间[0,1]上的二维数据'''
data = np.array([[random.uniform(0,1) for i in range(2)] for j in range(400)])


'''初始化隶属度矩阵(聚成4类)'''
'''
cntr:聚类中心
u:最后的隶属度矩阵
u0:初始化的隶属度矩阵
d:是一个矩阵,记录每一个点到聚类中心的欧式距离
jm:是目标函数的优化历史
p:p是迭代的次数
fpc:全称是fuzzy partition coefficient, 是一个评价分类好坏的指标,它的范围是0到1, 1表示效果最好,后面可以通过它来选择聚类的个数。
'''
cntr, u, u0, d, jm, p, fpc = fuzz.cluster.cmeans(data.T, 4, 2, error=0.0001, maxiter=1000)


'''迭代计算'''
cntr, u, u0, d, jm, p, fpc = fuzz.cluster.cmeans(data.T, 4,2, error=0.0001, maxiter=1000)


'''获得聚类结果'''
cluster_membership = np.argmax(u, axis=0)


'''绘制聚类结果'''
#将数据分类
fdata=data.tolist()
X1=[]
Y1=[]
X2=[]
Y2=[]
X3=[]
Y3=[]
X4=[]
Y4=[]
for i in range(400):
    if cluster_membership[i]==0:
        X1.append(fdata[i][0])
        Y1.append(fdata[i][1])
    if cluster_membership[i]==1:
        X2.append(fdata[i][0])
        Y2.append(fdata[i][1])
    if cluster_membership[i]==2:
        X3.append(fdata[i][0])
        Y3.append(fdata[i][1])
    if cluster_membership[i]==3:
        X4.append(fdata[i][0])
        Y4.append(fdata[i][1])

#聚类图
plt.scatter(X1,Y1,c='red',marker='o')
plt.scatter([cntr[0][0]],[cntr[0][1]],marker='>',c="black",label='聚类中心1')
plt.scatter(X2,Y2,c='blue',marker="o")
plt.scatter([cntr[1][0]],[cntr[1][1]],marker='<',c="black",label="聚类中心2")
plt.scatter(X3,Y3,c='green',marker="o")
plt.scatter([cntr[2][0]],[cntr[2][1]],marker='^',c="black",label="聚类中心3")
plt.scatter(X4,Y4,c='orange',marker="o")
plt.scatter([cntr[3][0]],[cntr[3][1]],marker="D",c="black",label="聚类中心4")
plt.legend()
plt.xlabel("x")
plt.ylabel("y")
plt.title("聚类图")
plt.show()

print(cluster_membership)
'''
print("cntr:\n{}".format(cntr))
print("u:\n{}".format(u))
print("u0:\n{}".format(u0))
print("d:\n{}".format(d))
print("jm:\n{}".format(jm))
print("p:\n{}".format(p))
print("fpc:\n{}".format(fpc))
'''


http://www.niftyadmin.cn/n/5141402.html

相关文章

oracle sqlplus的使用 ,查询oracle实例名和服务名,查询oracle容器,切换oracle容器

Oracle的sqlplus是与oracle数据库进行交互的客户端工具&#xff08;oracle数据库自带的客户端工具&#xff09;&#xff0c;借助sqlplus可以查看、修改数据库记录。在sqlplus中&#xff0c;可以运行sql*plus命令与sql语句。 1。先使用root账户登陆系统后&#xff0c;使用su - o…

UDP网络编程的接受与发送信息

/发送端B>可以接受数据 public class UDPSenderB {public static void main(String[] args) throws IOException {//创建一个DatagramSocket 对象&#xff0c;准备发送和接受数据DatagramSocket socket new DatagramSocket(9998);//将需要发送的数据&#xff0c;封装到Data…

十九、类型信息(5)

动态代理 _代理_是基本的设计模式之一。一个对象封装真实对象&#xff0c;代替其提供其他或不同的操作—这些操作通常涉及到与“真实”对象的通信&#xff0c;因此代理通常充当中间对象。这是一个简单的示例&#xff0c;显示代理的结构&#xff1a; interface Interface {voi…

Nacos 原理详解

一. 背景 现如今市面上注册中心的轮子很多&#xff0c;我实际使用过的就有三款&#xff1a;Eureka、Nacos&#xff0c;Zookeeper、Consul 由于当前参与Nacos 集群的维护和开发工作&#xff0c;期间也参与了 Nacos 社区的一些开发和 bug fix 工作&#xff0c;过程中对 Nacos 原…

基站/手机是怎么知道信道情况的?

在无线通信系统中&#xff0c;信道的情况对信号的发送起到至关重要的作用&#xff0c;基站和手机根据信道的情况选择合适的资源配置和发送方式进行通信&#xff0c;那么基站或者手机是怎么知道信道的情况呢&#xff1f; 我们先来看生活中的一个例子&#xff0c;从A地发货到B地…

PHP在线客服系统平台系统源码+完全开源 带完整的搭建教程

在线客服系统已经成为企业与用户进行实时沟通的重要工具。PHP作为一种流行的服务器端脚本语言&#xff0c;具有高效、稳定和易用性等优点&#xff0c;因此被广泛应用于在线客服系统的开发。今天罗峰来给大家介绍一款PHP在线客服系统平台系统源码&#xff0c;源码完全开源&#…

AM@微分方程相关概念@线性微分方程@一阶线性微分方程的通解

文章目录 abstract引言 一般的微分方程常微分方程微分方程的解隐式解通解和特解初始条件初值问题微分方程的积分曲线 线性微分方程一阶线性微分方程一阶齐次和非齐次线性微分方程一阶齐次线性微分方程的解一阶非齐次线性微分方程的解 abstract AM微分方程相关概念线性微分方程…

【6】c++11新特性(稳定性和兼容性)—>Lambda表达式

基本用法 lambda表达式是c最重要也是最常用的特性之一&#xff0c;这是现代编程语言的一个特点&#xff0c;lambda表达式有如下的一些优点&#xff1a; &#xff08;1&#xff09;声明式的编成风格&#xff1a;就地匿名定义目标函数活着函数对象&#xff0c;不需要额外写一个命…