ファジー C 平均法アルゴリズム (FCM)

この記事のコードとデータのアドレスは github にアップロードされています: https://github.com/helloWorldchn/MachineLearning

1. FCM アルゴリズムの概要

1. ファジィ集合論

LAZadeh は 1965 年に初めてファジー集合理論を提案しました。この理論では、メンバーシップ度の値が 0 または 1 ではない従来のハード クラスタリング アルゴリズムの厳密なメンバーシップ関係に対して、ファジー集合理論を使用して元のメンバーシップ度を 0 の間に拡張します。 1. その間の任意の値で、サンプルはメンバーシップの度合いが異なる異なるクラスターに属することができます。これにより、実際のデータセットのクラスタリングアルゴリズムの処理能力が大幅に向上し、人々の視界にはあいまいなクラスタリングが表示されます。FCM アルゴリズムは、データ マイニング、機械学習、コンピューター ビジョン、画像処理で広く使用されています。

2. FCMアルゴリズム

ファジー C 平均法クラスタリング (Fuzzy C-means) アルゴリズムは、 FCMアルゴリズムと呼ばれ、ソフト クラスタリング法の一種です。FCM アルゴリズムは、1974 年に Dunn によって最初に提案され、その後 Bezdek によって推進されました。

ハード クラスタリング アルゴリズムには分類時に厳格な基準があり、その基準に従って分類結果はどちらか一方になります。
ソフト クラスタリング アルゴリズムは、メンバーシップの次数にさらに注意を払います。メンバーシップの次数は [0,1] の間です。各オブジェクトには各クラスに属するメンバーシップの次数があり、すべてのメンバーシップの次数の合計は 1 になります。程度が高いほど類似性が高くなります。

3. アルゴリズム思考

ファジー C 平均法クラスタリング (FCM) アルゴリズムは、ソフト クラスタリング手法です。この手法の考え方は、
メンバーシップの度合いを使用して各データ間の関係を表現し、各データが属するクラスタのクラスタリングを決定することです。ポイントが属するクラスメソッド。同時に、FCM アルゴリズムは目的関数に基づくアルゴリズムでもあり、n 個のデータを含むデータセットがあるとします: X = { x 1 , x 2 , … xi , … , xn } X=\left\{\right .x_1,x_2 ,…x_i,…,x_n\left\}\right。バツ={ バツ1バツ2バツ私はバツ}X i X_iバツ私は是第 i i i特徴ベクトル;X ij X_{ij}バツイジXiXiX i番目j属性。各サンプルにはdd がd属性。FCM アルゴリズムは、このデータセットをKKクラスKKKKは 1 より大きい正の整数です。ここで、KKKクラスのクラスター中心は [ v 1 , v 2 , … , vn ] [v_1, v _2, …, v_n]です[ v1v2v]
FCM の目的関数と制約は次のとおりです。

J ( U , V ) = ∑ i = 1 n ∑ j = 1 kuijmdij 2 J(U,V)=\displaystyle\sum_{i=1}^{n} \displaystyle\sum_{j=1}^{k } u_{ij}^md_{ij}^2J ( U V )=i = 1j = 1あなたijメートルdij2

∑ j = 1 kuij = 1 , uij ∈ [ 0 , 1 ] \displaystyle\sum_{j=1}^{k} u_{ij}=1, u_{ij}∈[0,1]j = 1あなたイジ=1 あなたイジ[ 0 ,1 ]

其中, u i j u_{ij} あなたイジはサンプル点xi x_iですバツ私はおよびクラスター中心vj v_jvjメンバーシップの次数、m はファジーインデックス (m>1)、dij d_{ij}dイジはサンプル点xi x_iですバツ私はおよびクラスター中心vj v_jvj距離は通常ユークリッド距離です。クラスタリングは、制約の下で目的関数の最小値を見つけることです。FCM アルゴリズムは、目的関数の反復最適化を通じてサンプル セットのファジー分類を取得します。

目的関数 J の最小値を求めるために、制約を満たす条件で目的関数にラグランジュ乗数法を使用し、メンバーシップ行列 U とクラスタリング中心vj v_jを取得します。vj

uij = 1 ∑ c = 1 k ( dijdik ) 2 m − 1 u_{ij}=\frac{1}{\displaystyle\sum_{c=1}^{k} (\frac{d_{ij}}{d_ {ik}}) ^\frac{2}{m-1}}あなたイジ=c = 1(ddイジm 121

vj = ∑ i = 1 nuijmxi ∑ i = 1 nuijm v_j=\frac{\displaystyle\sum_{i=1}^{n} u_{ij}^m x_i }{\displaystyle\sum_{i=1}^{ n} u_{ij}^m }vj=i = 1あなたijメートルi = 1あなたijメートルバツ私は

4. アルゴリズムのステップ

アルゴリズムの具体的な説明は次のとおりです。

入力: クラスターの数 K、初期クラスター中心X = { x 1 , x 2 , … xi , … , xn } X=\left\{\right.x_1,x_2,...x_i,...,x_n\left\} \右。バツ={ バツ1バツ2バツ私はバツ}、ファジー インデックス m、終了エラー
出力: クラスター中心[ v 1 , v 2 , … , vk ] [v_1,v _2,…,v_k][ v1v2v]、メンバーシップ度行列uij u_{ij}あなたイジ
ステップ 1: パラメータ値 k、m および反復許容誤差 ε を初期化する;
ステップ 2: 反復回数 l=0 およびメンバーシップ度行列 U(0) を初期化する;
ステップ 3: 式に従ってメンバーシップ度行列と新しい集計行列を計算または更新する前のステップクラスセンターで。
ステップ 4: J l J^lを比較するJlJ ( l − 1 ) J^{(l-1)}J( l 1 );若∣ ∣ J l − J ( l − 1 ) ∣ ∣ ≤ ε || J^{l} - J^{(l-1)} || ≤ ε∣∣ JJ( l 1 ) ∣∣εの場合、反復停止条件が満たされ、反復が停止します。それ以外の場合は、 l = l + 1 l=l+1を設定します。=+1、ステップ 3 に戻り、繰り返しを続けます。

疑似コードは次のとおりです。

输入:数据集合X, 聚类的类别数k ,迭代次数阈值 T ,迭代次数 t ;
输出:聚类中心V, 隶属度矩阵U u = 进行初始化;
	init U;    //隶属度矩阵U初始化
	calculate v ;//根据公式计算聚类中心点
	calculate u ;//根据公式计算隶属度
	更新并组成隶属度矩阵U
	calculate J;  //计算目标函数 J ;
	t += 1; 
	if t > T
		return C
	else
		返回步骤 2;
	end if

FCM のフローチャートは次のとおりです。
FCMのフローチャート

2. コードの実装 (Python3)

この記事で使用するデータ セットは UCI データ セットであり、テストにはアイリス データ セット Iris、ワイン データ セット Wine、小麦種子データ セット シードを使用します。この論文では、これら 3 つのデータ セットを UCI 公式 Web サイトからダウンロードします。そしてそれらを同じフォルダー内の Python ファイルに置きます。同時に、プログラムの必要性により、データセットの列の位置がわずかに変更されました。データセットの具体的な情報は次のとおりです。

データセット サンプル数 属性次元 カテゴリの数
虹彩 150 4 3
ワイン 178 3 3
種子 210 7 3

データセットは私のホームページのリソースから入手できます。ポイントは無料でダウンロードできます。ダウンロードできない場合は、私にプライベートメッセージを送ってください。

1. Python3 コードの実装

from pylab import *
import pandas as pd
import numpy as np
import operator
import math
import matplotlib.pyplot as plt
import random
from sklearn.decomposition import PCA
from sklearn.preprocessing import LabelEncoder
from sklearn.metrics import normalized_mutual_info_score  # NMI
from sklearn.metrics import rand_score  # RI
from sklearn.metrics import accuracy_score  # ACC
from sklearn.metrics import f1_score  # F-measure

# 数据保存在.csv文件中
iris = pd.read_csv("dataset/iris.csv", header=0)  # 鸢尾花数据集 Iris  class=3
wine = pd.read_csv("dataset/wine.csv")  # 葡萄酒数据集 Wine  class=3
seeds = pd.read_csv("dataset/seeds.csv")  # 小麦种子数据集 seeds  class=3
wdbc = pd.read_csv("dataset/wdbc.csv")  # 威斯康星州乳腺癌数据集 Breast Cancer Wisconsin (Diagnostic)  class=2
glass = pd.read_csv("dataset/glass.csv")  # 玻璃辨识数据集 Glass Identification  class=6
df = iris  # 设置要读取的数据集
# print(df)
columns = list(df.columns)  # 获取数据集的第一行,第一行通常为特征名,所以先取出
features = columns[:len(columns) - 1]  # 数据集的特征名(去除了最后一列,因为最后一列存放的是标签,不是数据)
dataset = df[features]  # 预处理之后的数据,去除掉了第一行的数据(因为其为特征名,如果数据第一行不是特征名,可跳过这一步)
class_labels = list(df[columns[-1]])  # 原始标签
attributes = len(df.columns) - 1  # 属性数量(数据集维度)
k = 3  # 聚类簇数
MAX_ITER = 20  # 最大迭代数
n = len(dataset)  # 样本数
m = 2.00  # 模糊参数


# 初始化模糊矩阵U
def initializeMembershipMatrix():
    membership_mat = list()
    for i in range(n):
        random_num_list = [random.random() for i in range(k)]
        summation = sum(random_num_list)
        temp_list = [x / summation for x in random_num_list]  # 首先归一化
        membership_mat.append(temp_list)
    return membership_mat


# 计算类中心点
def calculateClusterCenter(membership_mat):
    cluster_mem_val = zip(*membership_mat)
    cluster_centers = list()
    cluster_mem_val_list = list(cluster_mem_val)
    for j in range(k):
        x = cluster_mem_val_list[j]
        x_raised = [e ** m for e in x]
        denominator = sum(x_raised)
        temp_num = list()
        for i in range(n):
            data_point = list(dataset.iloc[i])
            prod = [x_raised[i] * val for val in data_point]
            temp_num.append(prod)
        numerator = map(sum, zip(*temp_num))
        center = [z / denominator for z in numerator]  # 每一维都要计算。
        cluster_centers.append(center)
    return cluster_centers


# 更新隶属度
def updateMembershipValue(membership_mat, cluster_centers):
    #    p = float(2/(m-1))
    data = []
    for i in range(n):
        x = list(dataset.iloc[i])  # 取出文件中的每一行数据
        data.append(x)
        distances = [np.linalg.norm(list(map(operator.sub, x, cluster_centers[j]))) for j in range(k)]
        for j in range(k):
            den = sum([math.pow(float(distances[j] / distances[c]), 2) for c in range(k)])
            membership_mat[i][j] = float(1 / den)
    return membership_mat, data


# 得到聚类结果
def getClusters(membership_mat):
    cluster_labels = list()
    for i in range(n):
        max_val, idx = max((val, idx) for (idx, val) in enumerate(membership_mat[i]))
        cluster_labels.append(idx)
    return cluster_labels


def fuzzyCMeansClustering():
    # 主程序
    membership_mat = initializeMembershipMatrix()
    curr = 0
    start = time.time()  # 开始时间,计时
    while curr <= MAX_ITER:  # 最大迭代次数
        cluster_centers = calculateClusterCenter(membership_mat)
        membership_mat, data = updateMembershipValue(membership_mat, cluster_centers)
        cluster_labels = getClusters(membership_mat)
        curr += 1

    print("用时:{0}".format(time.time() - start))
    # print(membership_mat)
    return cluster_labels, cluster_centers, data, membership_mat


labels, centers, data, membership = fuzzyCMeansClustering()


def clustering_indicators(labels_true, labels_pred):
    if type(labels_true[0]) != int:
        labels_true = LabelEncoder().fit_transform(df[columns[len(columns) - 1]])  # 如果标签为文本类型,把文本标签转换为数字标签
    f_measure = f1_score(labels_true, labels_pred, average='macro')  # F值
    accuracy = accuracy_score(labels_true, labels_pred)  # ACC
    normalized_mutual_information = normalized_mutual_info_score(labels_true, labels_pred)  # NMI
    rand_index = rand_score(labels_true, labels_pred)  # RI
    return f_measure, accuracy, normalized_mutual_information, rand_index


F_measure, ACC, NMI, RI = clustering_indicators(class_labels, labels)
print("F_measure:", F_measure, "ACC:", ACC, "NMI", NMI, "RI", RI)
# print(centers)
center_array = array(centers)
label = array(labels)
datas = array(data)
if attributes > 2:
    dataset = PCA(n_components=2).fit_transform(dataset)  # 如果属性数量大于2,降维
# 做散点图
plt.scatter(dataset[:, 0], dataset[:, 1], marker='o', c='black', s=7)  # 原图
plt.show()
colors = np.array(["red", "blue", "green", "orange", "purple", "cyan", "magenta", "beige", "hotpink", "#88c999"])
# 循换打印k个簇,每个簇使用不同的颜色
for i in range(k):
    plt.scatter(dataset[nonzero(label == i), 0], dataset[nonzero(label == i), 1], c=colors[i], s=7)
# plt.scatter(center_array[:, 0], center_array[:, 1], marker='x', color='m', s=30)  # 聚类中心
plt.show()

2. クラスタリング結果の分析

本稿では、評価指標としてF値(F-measure、FM)、精度率(Accuracy、ACC)、標準相互情報量(NMI)、ランド指数(Rand Index、RI)を選定し、その値を算出する。範囲は [ 0,1] で、値が大きいほど、クラスタリング結果が期待どおりになります。

F 値は、適合率 (Precision) と再現率 (Recall) の 2 つの指標を組み合わせたもので、適合率と再現率の調和平均値であり、計算式は次の式で示されます。

精度 = TPTP + FP 精度 =\frac{TP}{TP+FP}精度_ _ _ _ _ _=TP+FPTP

リコール = TPTP + FN リコール =\frac{TP}{TP+FN}全て記録する=TP+FNTP

F − 測定値 = 2 再現率 × 精度 再現率 + 精度 F-measure=\frac{2Recall \times Precision}{Recall+Precision}F確か_ _ _ _=全て記録する+精度_ _ _ _ _ _2録音する_ _×精度_ _ _ _ _ _

ACC は、データセット内のサンプルの総数に対する正しく分類されたサンプルの数の比率であり、計算式は次のとおりです。

ACC = TP + TNTP + TN + FP + FN ACC=\frac{TP+TN}{TP+TN+FP+FN}CC _=TP+テネシー州+FP+FNTP+TN

このうち、TP(True Positive)は陽性クラスを予測するサンプル数を陽性クラス数として示し、TN(True Negative)は陰性クラスを予測するサンプル数を陰性クラス数として示し、FP( False Positive)は、陰性クラスが予測されることを示します。FN(False Negative)は、陽性クラスを予測するサンプル数を陰性クラスの数として表します。

NMIは、クラスタリング結果と既知のカテゴリラベルの一致度を定量化するために使用され、ACCと比較して、NMIの値はカテゴリラベルの配置に影響されません。次のように計算されます。

NMI = I ( U , V ) H ( U ) H ( V ) NMI=\frac{I\left(U,V\right)}{\sqrt{H\left(U\right)H\left(V\右)}}ニューメキシコ州I=H()H( V ) (V )

このうち、H(U) は正しい分類のエントロピーを表し、H(V) はアルゴリズムによって得られた結果のエントロピーを表します。

具体的な実装コードは以下の通りです。
データセットに与えられた正しいラベルがデジタルラベルではなくテキストタイプの場合があるため、データセットのラベルがデジタルタイプであるかどうかを計算前に判断する必要があり、そうでない場合は計算する必要があります。 、デジタルタイプに変換します

def clustering_indicators(labels_true, labels_pred):
    if type(labels_true[0]) != int:
        labels_true = LabelEncoder().fit_transform(df[columns[len(columns) - 1]])  # 如果标签为文本类型,把文本标签转换为数字标签
    f_measure = f1_score(labels_true, labels_pred, average='macro')  # F值
    accuracy = accuracy_score(labels_true, labels_pred)  # ACC
    normalized_mutual_information = normalized_mutual_info_score(labels_true, labels_pred)  # NMI
    rand_index = rand_score(labels_true, labels_pred)  # RI
    return f_measure, accuracy, normalized_mutual_information, rand_index


F_measure, ACC, NMI, RI = clustering_indicators(labels_number, labels)
print("F_measure:", F_measure, "ACC:", ACC, "NMI", NMI, "RI", RI)

クラスター分析インデックスを計算する必要がある場合は、上記のコードを実装コードに挿入するだけです。

3. クラスタリング結果

  1. アイリス データセット アイリス
    Iris アヤメ データセットの元の画像
Iris アヤメ データセットの元の画像

アヤメアヤメデータセットの FCM クラスタリング効果図

アヤメアヤメデータセットの FCM クラスタリング効果図
  1. ワイン データセット ワイン

ワイン wine データセットの元の画像

ワイン wine データセットの元の画像

Wine ワイン データセットの FCM クラスタリング効果図

Wine ワイン データセットの FCM クラスタリング効果図
  1. 小麦種子データセット

ここに画像の説明を挿入

Seeds 小麦種子データセットの元の画像

Seeds小麦種子データセットのFCMクラスタリング効果図

Seeds小麦種子データセットのFCMクラスタリング効果図

4. FCMアルゴリズムの不備

FCM アルゴリズムの中核となるステップは、クラスター内の最小距離を達成するために、継続的な反復を通じてクラスターの中心を更新することです。このアルゴリズムの時間計算量は非常に低いため、このアルゴリズムは広く使用されていますが、アルゴリズムには多くの欠点があり、主な欠点は次のとおりです。

  1. FCM クラスタリングのクラスタ数はユーザーが指定する必要があります。FCM アルゴリズムでは、最初にユーザーがクラスター数の K 値を指定する必要があります。K 値の決定は、クラスタリングの結果に直接影響します。通常、K 値は、ユーザーが自身の経験と理解に基づいて指定する必要があります。データセットに依存するため、指定された値は理想的ではない可能性があり、クラスタリングの結果は保証されません。
  2. FCM アルゴリズムの最初の中心点の選択はランダムな方法です。FCM アルゴリズムは、初期中心点の選択に大きく依存します。初期中心点が誤って選択されると、その後のクラスタリング プロセスに大きな影響を及ぼし、最適なクラスタリング結果が得られない可能性があります。また、クラスタリングの反復回数も減少する可能性があります。最初の中心点のランダムな選択には大きな不確実性があり、クラスタリングの効果に直接影響します。
  3. FCM は類似性の測定にユークリッド距離を使用しますが、非凸データセットでは良好なクラスタリング効果を達成するのは困難です。

おすすめ

転載: blog.csdn.net/qq_43647936/article/details/130686246