news 2026/4/22 4:59:58

使用FCM进行编码解码Python实现代码

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
使用FCM进行编码解码Python实现代码

文章目录

  • 代码整体结构
  • 第 1 部分:生成二维合成数据
    • 固定随机种子
    • means中心位置
    • covs形状
    • sizes点数
    • 生成数据
    • 裁剪到[0,1]
  • 第 2 部分:初始化隶属度矩阵
    • 为什么要按列归一化?
    • 这一步的意义
  • 第 3 部分:更新聚类中心
  • 第 4 部分:计算距离(每个样本到每个中心的距离)
    • 为什么要防止除零?
  • 第 5 部分:更新隶属度矩阵
    • 为什么先算距离?
    • 关键部分
    • 怎么理解ratio?
    • 总结
  • 第 6 部分:FCM 主循环
    • 初始化
    • 开始迭代
    • 为什么看U - U_old?
  • 第 7 部分:解码 / 重构
    • 最终结果
    • 为什么这就是解码?
  • 第 8 部分:重构误差
  • 第 9 部分:画图
    • 1 原始数据
    • 2 重构数据
    • 3 聚类中心
  • 第 10 部分:主程序
    • 生成数据
    • 设置参数
    • 运行FCM
    • 重构
    • 算误差
    • 输出结果
    • 画图
  • 10 总结
  • 代码
    • 1 导包
    • 2 生成二维合成数据
    • 3 初始化隶属度矩阵
    • 4 更新聚类中心
    • 5 计算距离
    • 6 更新隶属度矩阵
    • 7 FCM主函数
    • 8 解码(解粒化)
    • 9 重构误差
    • 10 完整代码

代码整体结构

1. generate_data() # 生成二维合成数据 2. initialize_membership() # 初始化隶属度矩阵 3. update_centers() # 更新聚类中心 4. compute_distances() # 计算样本到中心的距离 5. update_membership() # 更新隶属度矩阵 6. fcm() # FCM主循环 7. reconstruct_data() # 解码/重构 8. reconstruction_error() # 计算重构误差 9. plot_result() # 画图 10. main # 主程序入口

第 1 部分:生成二维合成数据

固定随机种子

means中心位置

covs形状

sizes点数

生成数据

裁剪到[0,1]

第 2 部分:初始化隶属度矩阵

为什么要按列归一化?

这一步的意义

给每个样本随机分配一个“模糊归属”

第 3 部分:更新聚类中心



哪个点对某个簇的隶属度大,它对这个簇中心的贡献就更大。所以聚类中心不是简单平均,而是加权平均。

第 4 部分:计算距离(每个样本到每个中心的距离)


为什么要防止除零?

第 5 部分:更新隶属度矩阵

为什么先算距离?

因为 FCM 的思想就是:离哪个中心近,就更属于哪个中心。所以要先知道每个点离各中心有多远。

关键部分

怎么理解ratio?

总结

隶属度是根据相对距离算出来的。

越近 → 隶属度越大 越远 → 隶属度越小

第 6 部分:FCM 主循环

初始化

开始迭代

为什么看U - U_old?

因为 FCM 最终要收敛到一个稳定状态。
如果两次隶属度矩阵几乎没变化,说明:

中心也基本稳定了 隶属度也基本稳定了 可以停止迭代

第 7 部分:解码 / 重构


最终结果

为什么这就是解码?

因为编码时,一个点被表示成:它对各中心的隶属度向量
现在解码时,又根据:隶属度、中心位置把它还原成二维点

第 8 部分:重构误差

第 9 部分:画图

1 原始数据

plt.scatter(X[:,0],X[:,1],marker='x',s=12,alpha=0.45,label='Original data')

2 重构数据

plt.scatter(X_hat[:,0],X_hat[:,1],marker='+',s=18,alpha=0.95,label='Reconstruction data')

3 聚类中心

plt.scatter(centers[:,0],centers[:,1],marker='o',s=80,alpha=0.9,label='Centers')

第 10 部分:主程序

生成数据

X=generate_data(seed=42)

设置参数

c=8m=2.0

运行FCM

centers,U=fcm(X,c=c,m=m,max_iter=200,tol=1e-5,seed=42)

重构

X_hat=reconstruct_data(centers,U,m)

算误差

V=reconstruction_error(X,X_hat)

输出结果

print("聚类中心 centers =")print(centers)print("\n隶属度矩阵 U 的形状 =",U.shape)print("重构误差 V =",V)

画图

plot_result(X,X_hat,centers)

10 总结

这段代码首先构造了一个二维合成数据集,然后使用 FCM 算法对数据进行模糊聚类,得到聚类中心和隶属度矩阵。这里的隶属度矩阵就是数据的编码结果,因为它表示每个样本对各个原型的模糊归属。接着利用聚类中心和隶属度矩阵,通过加权平均公式对每个样本进行解码重构,得到 reconstruction data,最后通过均方误差评价原始数据与重构数据之间的差异,并可视化展示结果。

代码

1 导包

importnumpyasnpimportmatplotlib.pyplotasplt

2 生成二维合成数据

1000 个点 6 组高斯分布 做过归一化
defgenerate_data(seed=42):np.random.seed(seed)means=np.array([[0.18,0.82],[0.20,0.55],[0.30,0.62],[0.42,0.40],[0.68,0.34],[0.82,0.18]])covs=[[[0.002,-0.001],[-0.001,0.006]],[[0.003,0.000],[0.000,0.005]],[[0.004,-0.002],[-0.002,0.006]],[[0.004,0.000],[0.000,0.003]],[[0.008,-0.004],[-0.004,0.003]],[[0.002,-0.001],[-0.001,0.002]]]sizes=[170,170,160,170,180,150]# 总共1000点X_list=[]formean,cov,sizeinzip(means,covs,sizes):pts=np.random.multivariate_normal(mean,cov,size)X_list.append(pts)X=np.vstack(X_list)X=np.clip(X,0,1)# 限制在 [0,1]returnX

3 初始化隶属度矩阵

definitialize_membership(n_samples,c):U=np.random.rand(c,n_samples)U=U/np.sum(U,axis=0,keepdims=True)returnU

4 更新聚类中心

defupdate_centers(X,U,m):Um=U**m centers=(Um @ X)/np.sum(Um,axis=1,keepdims=True)returncenters

5 计算距离

defcompute_distances(X,centers):# 返回 shape = (c, N)diff=X[None,:,:]-centers[:,None,:]dist=np.linalg.norm(diff,axis=2)dist=np.fmax(dist,1e-10)# 防止除零returndist

6 更新隶属度矩阵

defupdate_membership(X,centers,m):dist=compute_distances(X,centers)# (c, N)c=centers.shape[0]n=X.shape[0]U_new=np.zeros((c,n))exponent=2.0/(m-1.0)foriinrange(c):ratio=(dist[i:i+1,:]/dist)**exponent U_new[i,:]=1.0/np.sum(ratio,axis=0)returnU_new

7 FCM主函数

deffcm(X,c=8,m=2.0,max_iter=200,tol=1e-5,seed=42):np.random.seed(seed)n_samples=X.shape[0]U=initialize_membership(n_samples,c)foriterationinrange(max_iter):U_old=U.copy()centers=update_centers(X,U,m)U=update_membership(X,centers,m)diff=np.linalg.norm(U-U_old)print(f"第{iteration+1}次迭代, 隶属度变化量 ={diff:.8f}")ifdiff<tol:print("FCM 收敛")breakcenters=update_centers(X,U,m)returncenters,U

8 解码(解粒化)

defreconstruct_data(centers,U,m):Um=U**m numerator=Um.T @ centers# (N, d)denominator=np.sum(Um,axis=0,keepdims=True).T# (N, 1)X_hat=numerator/denominatorreturnX_hat

9 重构误差

defreconstruction_error(X,X_hat):returnnp.mean(np.sum((X-X_hat)**2,axis=1))

10 完整代码

importnumpyasnpimportmatplotlib.pyplotasplt# ========== 1. 生成二维合成数据 ==========defgenerate_data(seed=42):np.random.seed(seed)means=np.array([[0.18,0.82],[0.20,0.55],[0.30,0.62],[0.42,0.40],[0.68,0.34],[0.82,0.18]])covs=[[[0.002,-0.001],[-0.001,0.006]],[[0.003,0.000],[0.000,0.005]],[[0.004,-0.002],[-0.002,0.006]],[[0.004,0.000],[0.000,0.003]],[[0.008,-0.004],[-0.004,0.003]],[[0.002,-0.001],[-0.001,0.002]]]sizes=[170,170,160,170,180,150]# 总共1000点X_list=[]formean,cov,sizeinzip(means,covs,sizes):pts=np.random.multivariate_normal(mean,cov,size)X_list.append(pts)X=np.vstack(X_list)X=np.clip(X,0,1)# 限制在 [0,1]returnX# ========== 2. 初始化隶属度矩阵 ==========definitialize_membership(n_samples,c):U=np.random.rand(c,n_samples)U=U/np.sum(U,axis=0,keepdims=True)returnU# ========== 3. 更新聚类中心 ==========defupdate_centers(X,U,m):Um=U**m centers=(Um @ X)/np.sum(Um,axis=1,keepdims=True)returncenters# ========== 4. 计算距离 ==========defcompute_distances(X,centers):# 返回 shape = (c, N)diff=X[None,:,:]-centers[:,None,:]dist=np.linalg.norm(diff,axis=2)dist=np.fmax(dist,1e-10)# 防止除零returndist# ========== 5. 更新隶属度矩阵 ==========defupdate_membership(X,centers,m):dist=compute_distances(X,centers)# (c, N)c=centers.shape[0]n=X.shape[0]U_new=np.zeros((c,n))exponent=2.0/(m-1.0)foriinrange(c):ratio=(dist[i:i+1,:]/dist)**exponent U_new[i,:]=1.0/np.sum(ratio,axis=0)returnU_new# ========== 6. FCM主函数 ==========deffcm(X,c=8,m=2.0,max_iter=200,tol=1e-5,seed=42):np.random.seed(seed)n_samples=X.shape[0]U=initialize_membership(n_samples,c)foriterationinrange(max_iter):U_old=U.copy()centers=update_centers(X,U,m)U=update_membership(X,centers,m)diff=np.linalg.norm(U-U_old)print(f"第{iteration+1}次迭代, 隶属度变化量 ={diff:.8f}")ifdiff<tol:print("FCM 收敛")breakcenters=update_centers(X,U,m)returncenters,U# ========== 7. 解码 / 重构 ==========defreconstruct_data(centers,U,m):Um=U**m numerator=Um.T @ centers# (N, d)denominator=np.sum(Um,axis=0,keepdims=True).T# (N, 1)X_hat=numerator/denominatorreturnX_hat# ========== 8. 重构误差 ==========defreconstruction_error(X,X_hat):returnnp.mean(np.sum((X-X_hat)**2,axis=1))# ========== 9. 画图 ==========defplot_result(X,X_hat,centers):plt.figure(figsize=(7,6))plt.scatter(X[:,0],X[:,1],marker='x',s=12,alpha=0.45,label='Original data')plt.scatter(X_hat[:,0],X_hat[:,1],marker='+',s=18,alpha=0.95,label='Reconstruction data')plt.scatter(centers[:,0],centers[:,1],marker='o',s=80,alpha=0.9,label='Centers')plt.xlabel(r'$x_1$')plt.ylabel(r'$x_2$')plt.xlim(0,1)plt.ylim(0,1)plt.legend()plt.title('FCM Granulation-Degranulation')plt.show()# ========== 10. 主程序 ==========if__name__=="__main__":X=generate_data(seed=42)# 论文二维图常用参数c=8m=2.0centers,U=fcm(X,c=c,m=m,max_iter=200,tol=1e-5,seed=42)X_hat=reconstruct_data(centers,U,m)V=reconstruction_error(X,X_hat)print("\n===== 结果输出 =====")print("聚类中心 centers =")print(centers)print("\n隶属度矩阵 U 的形状 =",U.shape)print("重构误差 V =",V)plot_result(X,X_hat,centers)
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/22 4:59:44

如何用3步实现效率突破:开源智能工具重构网盘资源获取体验

如何用3步实现效率突破&#xff1a;开源智能工具重构网盘资源获取体验 【免费下载链接】baidupankey 项目地址: https://gitcode.com/gh_mirrors/ba/baidupankey 在数字化信息爆炸的时代&#xff0c;获取网络资源已成为日常工作和学习的必备技能。然而&#xff0c;面对…

作者头像 李华
网站建设 2026/4/22 4:52:38

基于鸿蒙Electron框架的碰撞效果测试与战斗系统——实战模拟

欢迎加入开源鸿蒙PC社区&#xff1a; https://harmonypc.csdn.net/ atomgit开源仓库地址&#xff1a; https://atomgit.com/feng8403000/BattleSimulator 示例效果 项目背景 在游戏开发中&#xff0c;碰撞检测和战斗系统是两个核心组件。碰撞检测负责检测物体之间的交互&…

作者头像 李华
网站建设 2026/4/22 4:49:01

告别系统软键盘!Unity UGUI自制虚拟键盘全流程(附C#源码与预制体)

Unity UGUI虚拟键盘开发实战&#xff1a;跨平台输入解决方案 在触屏设备普及的今天&#xff0c;输入交互成为用户体验的关键环节。传统系统软键盘存在平台依赖性强、样式不可控、功能受限等问题&#xff0c;尤其对于教育平板、自助终端等专用设备&#xff0c;往往需要完全定制化…

作者头像 李华