PHPのファジーc-meansファジークラスタリングアルゴリズム

良い一日。



以下の投稿とコードは、ビジネス目的でアルゴリズムを使用することではなく、ファジーc-meansアルゴリズムがどのように機能するかを理解し、他の言語でのこのアルゴリズムの実装に弾みをつけたり、特定のコードをさらに改善したりすることを目的としています仕事の目的で使用します。











一般的な情報





まず、クラスタリングとは何か、ファジークラスタリングの特別な点をすぐに伝える価値があります。



ウィクショナリーという言葉で説明されているように、クラスタリング

グループ化、オブジェクトのセットを互いに素なサブセットに分割、類似したオブジェクトで構成されるクラスター




この定義は非常に理解しやすく、追加の説明は必要ないと思います。



では、「ファジークラスタリング」とは何ですか?

ファジークラスタリングは、クラスタリングされたオブジェクトが特定の所属を持つ特定のクラスターに属し、従来のクラスタリングの場合のように明確ではないという事実によって、単純なクラスタリングと区別されます。 たとえば、ファジークラスタリングでは、オブジェクトAは、メンバーシップ0.9のクラスターK1、メンバーシップ0.04のクラスターK2、およびメンバーシップ0.06のクラスターK3に属します。 通常の(クリアな)クラスタリングでは、オブジェクトAはクラスターK1に割り当てられます。



このハブには、このアルゴリズムの数学的な説明があります。



PHPでのファジーc-meansの実装。



アルゴリズムの実装に直接移りましょう。 これを行うには、多かれ少なかれ実際の例での実装を検討します。 このような例は次のようになります-RGB値でピクセルをクラスター化しましょう。 実際に色で。 その結果、アルゴリズムの実行結果を明確に見ることができます。



以下はアルゴリズムのコードです。これについては、以下でさらに詳しく分析します。



RGB値によるクラスタリングポイントのファジーc-meansアルゴリズムの実装
define('EPLSION', 0.1); define('MAX_EXECUTION_CYCLES', 150); define('POINTS_COUNT', 100); define('CLUSTERS_NUM', 3); define('FUZZ', 1.5); class Point { public $r; public $g; public $b; } // Random values 0 - 1 function random_float ($min,$max) { return ($min+lcg_value()*(abs($max-$min))); } // Fuzzy C Means Algorithm function distributeOverMatrixU($arr, $m, &$centers) { $centers = generateRandomPoints(CLUSTERS_NUM); $MatrixU = fillUMatrix(count($arr), count($centers)); $previousDecisionValue = 0; $currentDecisionValue = 1; for($a = 0; $a < MAX_EXECUTION_CYCLES && (abs($previousDecisionValue - $currentDecisionValue) > EPLSION); $a++){ $previousDecisionValue = $currentDecisionValue; $centers = calculateCenters($MatrixU, $m, $arr); foreach($MatrixU as $key=>&$uRow){ foreach($uRow as $clusterIndex=>&$u){ $distance = evklidDistance3D($arr[$key], $centers[$clusterIndex]); $u = prepareU($distance, $m); } $uRow = normalizeUMatrixRow($uRow); } $currentDecisionValue = calculateDecisionFunction($arr, $centers, $MatrixU); } return $MatrixU; } function fillUMatrix($pointsCount, $clustersCount) { $MatrixU = array(); for($i=0; $i<$pointsCount; $i++){ $MatrixU[$i] = array(); for($j=0; $j<$clustersCount; $j++){ $MatrixU[$i][$j] = random_float(0, 1); } $MatrixU[$i] = normalizeUMatrixRow($MatrixU[$i]); } return $MatrixU; } function calculateCenters($MatrixU, $m, $points) { $MatrixCentroids = array(); for($clusterIndex=0; $clusterIndex < CLUSTERS_NUM; $clusterIndex++){ $tempAr = 0; $tempBr = 0; $tempAg = 0; $tempBg = 0; $tempAb = 0; $tempBb = 0; foreach($MatrixU as $key=>$uRow){ $tempAr += pow($uRow[$clusterIndex],$m); $tempBr += pow($uRow[$clusterIndex],$m) * $points[$key]->r; $tempAg += pow($uRow[$clusterIndex],$m); $tempBg += pow($uRow[$clusterIndex],$m) * $points[$key]->g; $tempAb += pow($uRow[$clusterIndex],$m); $tempBb += pow($uRow[$clusterIndex],$m) * $points[$key]->b; } $MatrixCentroids[$clusterIndex] = new Point(); $MatrixCentroids[$clusterIndex]->r = $tempBr / $tempAr; $MatrixCentroids[$clusterIndex]->g = $tempBg / $tempAg; $MatrixCentroids[$clusterIndex]->b = $tempBb / $tempAb; } return $MatrixCentroids; } function calculateDecisionFunction($MatrixPointX, $MatrixCentroids, $MatrixU) { $sum = 0; foreach($MatrixU as $index=>$uRow){ foreach($uRow as $clusterIndex=>$u){ $sum += $u * evklidDistance3D($MatrixCentroids[$clusterIndex], $MatrixPointX[$index]); } } return $sum; } function evklidDistance3D($pointA, $pointB) { $distance1 = pow(($pointA->r - $pointB->r),2); $distance2 = pow(($pointA->g - $pointB->g),2); $distance3 = pow(($pointA->b - $pointB->b),2); $distance = $distance1 + $distance2 + $distance3; return sqrt($distance); } function normalizeUMatrixRow($MatrixURow) { $sum = 0; foreach($MatrixURow as $u){ $sum += $u; } foreach($MatrixURow as &$u){ $u = $u/$sum; } return $MatrixURow; } function prepareU($distance, $m) { return pow(1/$distance , 2/($m-1)); } function generateRandomPoints($count){ $points = array_fill(0, $count, false); array_walk($points, function(&$value, $key){ $value = new Point(); $value->r = rand(20, 235); $value->g = rand(20, 235); $value->b = rand(20, 235); }); return $points; } $points = generateRandomPoints(POINTS_COUNT); $centers = array(); $matrixU = distributeOverMatrixU($points, FUZZ, $centers);
      
      









クラスタリングアルゴリズム自体を実際に起動する関数-distributeOverMatrixUからアルゴリズムの検討を開始します

その入力パラメーターは、クラスター化されたオブジェクトの配列(この場合、Pointクラスのオブジェクトを含むランダムに満たされた配列)と不確実性係数です。 戻り値はメンバーシップマトリックスです。 centers



パラメーターもin / out関数に追加されました。この関数では、アルゴリズムが実行された後、クラスターの中心が存在します。



新しいクラスターの中心を見つけてメンバーシップマトリックスを再計算する手順は、定数MAX_EXECUTION_CYCLESおよびEPSILONによって制限されます。MAX_EXECUTION_CYCLES-ステップ数を制限し、EPSILON-メンバーシップマトリックスを見つける精度を制限します。



アルゴリズムの各ステップは次のとおりです。

1)関数calculateCenters



を使用してクラスターの中心をcalculateCenters





2)次に、各オブジェクトについて、各クラスターの中心までのユークリッド距離を計算します(関数evklidDistance3D



-3次元空間)

3)指定されたオブジェクトのメンバーシップ係数u



を計算します( prepareU



関数)

4)与えられたオブジェクトの係数u



を正規化します(関数normalizeUMatrixRow





5)決定関数の値を計算します( calculateDecisionFunction



関数)

6)次に、決定関数の現在の値が以前の値と比較され、それらの差が設定されたEPSILONより小さい場合、アルゴリズムは動作を停止します。



各ステップについてもう少し詳しく:

1)中心は次の式に従って計算されます

画像

ここで、wk(x)はメンバーシップ係数、mは不確実性係数、xはオブジェクトです(アルゴリズム自体では、コンポーネントR、G、Bはxとして機能します)



2)3つの測定値についてユークリッド距離を計算します。 式は次のとおりです。

r = sqrt((r2-r1)^2 + (g2-g1)^2 + (b2-b1)^2);





ここで、r、g、bはRGBのコンポーネントです



3)メンバーシップ係数は次の式で計算されます

u = (1/d)^(2/(m-1))





ここで、dはオブジェクトからクラスターの中心までの距離、mは不確実性係数です。



4)すべてのオブジェクト所属係数の正規化-係数が合計1になるように変換します。 このオブジェクトのすべての係数の合計で各係数を実際に除算します



5)決定的関数は、メンバーシップ係数を掛けたクラスターの各中心までの各オブジェクトのすべてのユークリッド距離の合計を返します



6)決定関数の前の値と現在の値をモジュロ減算し、この差がEPSILONより小さい場合、アルゴリズムは停止し、見つかったメンバーシップ行列が返されます。



最後に、アルゴリズムの結果を示すスクリーンショットをいくつか追加したいと思います。

アルゴリズムが正しく機能し、色が似ているポイントを同じクラスターに割り当てることが図からわかります。

アルゴリズムのデモ










したがって、ファジーc-meansファジークラスタリングアルゴリズムの基本的な実装を紹介しました。 彼女があなたの役に立つことを願っています。

ご清聴ありがとうございました。



All Articles