grouping, partitioning of a set of objects into disjoint subsets, clusters consisting of similar objects
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
centers
was added to the in / out function, in which, after the algorithm is executed, the centers of our clusters will be.calculateCenters
evklidDistance3D
function is 3-dimensional space with us)u
for this object (the prepareU
function)u
for a given object (the normalizeUMatrixRow
function)calculateDecisionFunction
)r = sqrt((r2-r1)^2 + (g2-g1)^2 + (b2-b1)^2);
u = (1/d)^(2/(m-1))
,Source: https://habr.com/ru/post/208496/
All Articles