IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 【数据聚类】第三章第三节3:类K-Means算法之模糊K-均值算法(FCM算法) -> 正文阅读

[数据结构与算法]【数据聚类】第三章第三节3:类K-Means算法之模糊K-均值算法(FCM算法)

一:算法思想

  • 硬聚类:传统K-均值算法中,每个对象只能从属于所有类别中的一类,称之为硬聚类。这种聚类方法会带来一个问题:所有的对象对于计算聚类中心的贡献都是相同的,也就是说,对于从属于一个类的所有元素,算法是无法将其区分开来的。这种分配方式在处理一些复杂数据集合(例如数据有重叠)会造成类别指派不合理
  • 软聚类:一个对象可以从属于多个类别的聚类方法

模糊K-均值算法(FCM算法):对于每个类别,对象都对应一个取值范围在[0,1]的数值,它表示该对象从属于某一类别的可能性。一个对象对于所有类别的对应取值和应该为1。在更新簇中心点的过程中,该数值就反映了该对象对于这一类的贡献程度,根据贡献程度的不同,反映出对象更倾向于分配到哪个类别中

FCM算法与K-均值算法的目标函数类似

J m = ∑ k = 1 N ∑ j = 1 u i j m ∣ ∣ x i ? c j ∣ ∣ 2 , 1 ≤ m < ∞ J_{m}=\sum_{k=1}^{N}\sum_{j=1}u_{ij}^{m}||x_{i}-c_{j}||^{2},1\leq m <\infty Jm?=k=1N?j=1?uijm?xi??cj?21m<

其中

  • m ( > 1 ) m(>1) m(>1):模糊系数
  • N N N:样本数
  • C C C:聚类中心数
  • c j c_{j} cj?:第 j j j个聚类中心
  • x i x_{i} xi?:第 i i i个样本
  • u i j u_{ij} uij?:样本 x i x_{i} xi?对聚类中心 c j c_{j} cj?的隶属度,也即 x i x_{i} xi?属于 c j c_{j} cj?的概率。显然有 ∑ j = 1 C u i j \sum\limits_{j=1}^{C}u_{ij} j=1C?uij?=1

FCM算法通过更新 u i j u_{ij} uij? c j c_{j} cj?来迭代优化目标函数

u i j = 1 ∑ k = 1 C ( ∣ ∣ x i ? c j ∣ ∣ ∣ ∣ x i ? c k ∣ ∣ ) 2 m ? 1 u_{ij}=\frac{1}{\sum\limits_{k=1}^{C}(\frac{||x_{i}-c_{j}||}{||x_{i}-c_{k}||})^{\frac{2}{m-1}}} uij?=k=1C?(xi??ck?xi??cj??)m?12?1?

c j = ∑ i = 1 N u i j m x i ∑ i = 1 N u i j m c_{j}=\frac{\sum\limits_{i=1}^{N}u_{ij}^{m}x_{i}}{\sum\limits_{_{i=1}}^{N}u_{ij}^{m}} cj?=i=1?N?uijm?i=1N?uijm?xi??

FCM算法的收敛条件一般设置为两次迭代过程中计算的 S S E SSE SSE差值,其中 ξ \xi ξ是预先设定好的容忍误差,当两次迭代过程中计算的 S S E SSE SSE差值小于该预设值时,判定算法收敛

E ( t ) = ∣ ∣ S S E t ? S S E t ? 1 ∣ ∣ < ξ E(t)=||SSE^{t}-SSE^{t-1}||<\xi E(t)=SSEt?SSEt?1<ξ

二:算法流程

  1. 初始化隶属度矩阵 U 0 U^{0} U0:若有 N N N个样本,指定类别个数为 C C C,则隶属度矩阵应为 N N N× C C C
  2. 根据公式更新聚类中心 c j c_{j} cj?
  3. 根据公式更新隶属度矩阵(注意保存更新前的隶属度矩阵)
  4. 判断是否收敛,若收敛则停止迭代,反之返回步骤2

三:Python实现

import numpy as np
import copy

#  欧氏距离
def distance(data, centroid):
    return np.sqrt(np.sum(np.power(data-centroid, 2)))


def fcm(data_set, m, k, eps):
    example_nums = np.shape(data_set)[0]  # 样本数量
    cluster = np.zeros(example_nums)

    # 初始化隶属度矩阵
    random_mat = np.random.rand(example_nums, k)  # 生成随机矩阵
    random_mat_sum = 1 / np.sum(random_mat, axis=1)  # 求每一行的和
    membership_mat = np.multiply(random_mat.T, random_mat_sum)  # 使隶属度矩阵每一行和为1
    membership_mat = membership_mat.T
    membership_mat_old = np.zeros((example_nums, k))  # 便于迭代

    # 进行迭代,更新隶属度矩阵和聚类中心
    while True:
        centorids = np.empty((k, np.shape(data_set)[1]))
        # 由公式计算簇中心
        for j in range(k):
            centorids[j] = np.dot(membership_mat[:, j]**m, data_set) / (np.sum(membership_mat[:, j]**m))
        membership_mat_old = membership_mat.copy()

        # 根据公式计算新的隶属度矩阵
        for i in range(example_nums):
            for j in range(k):
                for z in range(k):
                    membership_mat[i, j] += ((distance(data_set[i], centorids[j])) / distance(data_set[i], centorids[z])) ** (2 / (m-1))
        membership_mat = 1 / membership_mat

        #  判断是否收敛
        if np.max(np.abs(membership_mat - membership_mat_old)) < eps:
            cluster = np.argmax(membership_mat, axis=1)
            return centorids, cluste
            

四:效果展示

import pandas as pd
import matplotlib.pyplot as plt
import FCM
import numpy as np

Iris_types = ['Iris-setosa', 'Iris-versicolor', 'Iris-virginica']  # 花类型
Iris_data = pd.read_csv('dataSet/Iris.csv')
# x_axis = 'PetalLengthCm'  # 花瓣长度
# y_axis = 'PetalWidthCm'   # 花瓣宽度
x_axis = 'SepalLengthCm'  # 花萼长度
y_axis = 'SepalWidthCm'  # 花萼宽度

examples_num = Iris_data.shape[0]  # 样本数量
train_data = Iris_data[[x_axis, y_axis]].values.reshape(examples_num, 2)  # 整理数据

# 归一化
min_vals = train_data.min(0)
max_vals = train_data.max(0)
ranges = max_vals - min_vals
normal_data = np.zeros(np.shape(train_data))
nums = train_data.shape[0]
normal_data = train_data - np.tile(min_vals, (nums, 1))
normal_data = normal_data / np.tile(ranges, (nums, 1))

#  训练参数
k = 3  # 簇数
max_iterations = 50  # 最大迭代次数
centroids, cluster = FCM.fcm(normal_data, 2, k, 1e-6)


plt.figure(figsize=(12, 5), dpi=80)

#  第一幅图是已知标签或全部数据
plt.subplot(1, 2, 1)

for Iris_type in Iris_types:
        plt.scatter(Iris_data[x_axis], Iris_data[y_axis], c='black')
plt.title('raw')

# 第二幅图是聚类结果
plt.subplot(1, 2, 2)
for centroid_id, centroid in enumerate(centroids):  # 非聚类中心
    current_examples_index = (cluster == centroid_id).flatten()
    plt.scatter(normal_data[current_examples_index, 0], normal_data[current_examples_index, 1])

for centroid_id, centroid in enumerate(centroids):  # 聚类中心
    plt.scatter(centroid[0], centroid[1], c='red', marker='x')
plt.title('label kemans')
plt.show()

在这里插入图片描述

五:算法缺陷

  • 对离群点十分敏感
  • 算法很可能是一个局部最优解
  • 算法运算量十分大
  • 算法伸缩性差,不适合处理大规模数据集合
  • 模糊系数 m m m对聚类结果影响非常大
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-07-04 23:13:18  更:2022-07-04 23:14:11 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 23:41:09-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码