<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
	<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Yushin</id>
	<title>Алговики - Вклад [ru]</title>
	<link rel="self" type="application/atom+xml" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Yushin"/>
	<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/ru/%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/Yushin"/>
	<updated>2026-10-22T19:53:46Z</updated>
	<subtitle>Вклад</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=21256</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=21256"/>
		<updated>2016-12-18T20:11:12Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|{{REVISIONUSER}}}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(Mdc^2i)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - количество итераций&lt;br /&gt;
| input_data         = &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt;, [количество наблюдений * размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt;, [количество наблюдений * количество кластеров]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;2i&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]] ([[#Вычислительное ядро алгоритма|1.3]]; [[#Схема реализации последовательного алгоритма|1.5]]; [[#Последовательная сложность алгоритма|1.6]]; [[#Информационный граф|1.7]]; [[#Масштабируемость алгоритма и его реализации|2.4]]; [[#Существующие реализации алгоритма|2.7]]), [[Участник:Yushin|Павел Юшин]] ([[#Общее описание алгоритма|1.1]]; [[#Математическое описание алгоритма|1.2]]; [[#Макроструктура алгоритма|1.4]]; [[#Ресурс параллелизма алгоритма|1.8]]; [[#Входные и выходные данные алгоритма|1.9]]; [[#Свойства алгоритма|1.10]])&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;[http://www.tandfonline.com/doi/abs/10.1080/01969727308546046 | J. C. Dunn. A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters. Journal of Cybernetics, volume 3,1973 - Issue 3, pp 32-57]&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов кластеризации, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров;&amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма не будут отличаться менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;[http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf | Нейский И.М. Классификация и сравнение методов кластеризации.// Интеллектуальные технологии и системы. Сборник учебно-методических работ и статей аспирантов и студентов. – М.: НОК «CLAIM», 2006. – Выпуск 8. – С. 130-142.]&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов, &amp;lt;math&amp;gt;X_i&amp;lt;/math&amp;gt; - набор входных векторов размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве нормы предлагается максимум-норма: &amp;lt;math&amp;gt;||W|| = \max_{i,j} |w_{i,j}|&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M&amp;lt;/math&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;0 &amp;lt; \sum_{i = 1}^M w_{ij} &amp;lt; M, j = 1, ..., c&amp;lt;/math&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда алгоритм принимает следующий вид:&lt;br /&gt;
&lt;br /&gt;
1) Задаем параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
2) Генерируем случайным образом матрицу нечеткого разбиения с учетом условий &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3) Рассчитываем центроиды (центры кластеров): &amp;lt;math&amp;gt;V_j = {{\sum_{i=1}^M w_{ij}^m * X_i} \over {\sum_{i=1}^M w_{ij}^m}}, j = 1, ..., c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Рассчитываем расстояния между объектами &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и центроидами:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_{ij} = {||X_i - V_j||}, i = 1,...,M; j = 1,...,c &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5) Пересчет элементов матрицы разбиения:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} &amp;gt;0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = {{1}\over {{ (\sum_{k=1}^c {{D_{ij}}\over{D_{ik}}} ) }^{2/(m-1)}}}, j = 1,...,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} =0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = \delta_{ij}, j = 1,...,c&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\delta_{ij}&amp;lt;/math&amp;gt; - символ Кронекера&lt;br /&gt;
&lt;br /&gt;
6) Если &amp;lt;math&amp;gt;|| F - F^{*} || &amp;lt; \varepsilon &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;F^{*}&amp;lt;/math&amp;gt; - матрица нечеткого разбиения предыдущей итерации, то идем далее, иначе возвращаемся на пункт 3.&lt;br /&gt;
&lt;br /&gt;
7) Конец.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром алгоритма являются следующие пункты:&lt;br /&gt;
&lt;br /&gt;
* Поиск &amp;lt;math&amp;gt;V_j&amp;lt;/math&amp;gt; - расчет центроидов (пункт 3 алгоритма)&lt;br /&gt;
* Нахождение &amp;lt;math&amp;gt;D_{ij}&amp;lt;/math&amp;gt; - расстояний между объектами (пункт 4 алгоритма)&lt;br /&gt;
* Пересчет &amp;lt;math&amp;gt;w_{ij}&amp;lt;/math&amp;gt; - элементов матрицы разбиения (пункт 5 алгоритма)&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Основные шаги при реализации алгоритма&lt;br /&gt;
*	Генерация случайной матрицы размера &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt;, проверка условий&lt;br /&gt;
*	Расчет центроидов – по сути, скалярное произведение с нормировкой&lt;br /&gt;
*	Расчет расстояний – в общепринятом случае является скалярным произведением&lt;br /&gt;
*	Пересчет матрицы – по сути, скалярное произведение&lt;br /&gt;
*	Проверка условий останова – вычисление нормы&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
    float ** FuzzyCMeans (float** X, c, m, eps){&lt;br /&gt;
        n = X.size();&lt;br /&gt;
        r = X[0].size();&lt;br /&gt;
        centers = generateZeroFill(c, r)&lt;br /&gt;
        Wprev = genetateRandFill(n, c);&lt;br /&gt;
        W = Wprev;&lt;br /&gt;
        while (true){&lt;br /&gt;
            // обновляем центры кластеров &lt;br /&gt;
            for (int i=0; i&amp;lt;c; i++){&lt;br /&gt;
                float * num = new float []();&lt;br /&gt;
                float den = 0;&lt;br /&gt;
                for (int j=0; j&amp;lt;n; j++){&lt;br /&gt;
                    num += pow(W[j][i], m) * X[j];&lt;br /&gt;
                    den+=pow(W[j][i], m);&lt;br /&gt;
                }&lt;br /&gt;
                centers[i] = num / den;&lt;br /&gt;
            }&lt;br /&gt;
            //обновляем вероятности W и считаем расстояние между матрицами W и Wprev&lt;br /&gt;
            float max_diff = 0;&lt;br /&gt;
            for (int i=0; i&amp;lt;n; i++)&lt;br /&gt;
                for (int j=0; j&amp;lt;c; j++){&lt;br /&gt;
                    total = 0;&lt;br /&gt;
                    for (int m=0; m&amp;lt;с; m++)&lt;br /&gt;
                        total += pow(distance(X[i], centers[j]) / distance(X[i], centers[m]), 2/(m-1));&lt;br /&gt;
                    W[i][j] = 1/total;&lt;br /&gt;
                    max_diff = max(abs(Wprev[i][j]-W[i][j]), max_diff);&lt;br /&gt;
                    Wprev[i][j] = W[i][j];&lt;br /&gt;
               }               &lt;br /&gt;
           if (max_diff &amp;lt; eps):                &lt;br /&gt;
                break;&lt;br /&gt;
        }&lt;br /&gt;
        return W;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Последовательная сложность алгоритма состоит из сложности каждой итерации умноженной на их количество. Так как число итераций заранее неизвестно и зависит от входных параметров, рассмотрим сложность на каждой итерации. Наибольшую сложность представляет собой пересчет матрицы, сложность которого &amp;lt;math&amp;gt;O(c^2 nd)&amp;lt;/math&amp;gt; (по сравнению со сложностью &amp;lt;math&amp;gt;O(cnd)&amp;lt;/math&amp;gt; расчета расстояний, вычисления центроидов и проверки условия останова). Итого общая сложность алгоритма &amp;lt;math&amp;gt;O(c^2 ndi)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
Информационный граф представлен на рисунке ниже.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 1, 2, совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз для каждого кластера. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 1&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 2&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m*X_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем вектор размера &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; и матрицу размера &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;. &lt;br /&gt;
Далее совершаем поэлементное сложение векторов и матриц соответственно, а затем делим каждый столбец в матрице на соответствующий элемент в векторе.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй ярус&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 3, 4, 5 также совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 3&#039;&#039;&#039;: обновление значения &amp;lt;math&amp;gt;w_{ij}&amp;lt;/math&amp;gt; по указанной в разделе 1.2 в пункте 5 формуле.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 4&#039;&#039;&#039;: &amp;lt;math&amp;gt;maximum = max(|w_{ij} - w_{ij}^{prev}|, maximum)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 5&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^{prev} = w_{ij}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем число &amp;lt;math&amp;gt;maximum&amp;lt;/math&amp;gt;. Далее находим максимальное значение из полученных величин для каждой ветки. Затем проверяем условие останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:Scheme3.JPG]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельная сложность алгоритма: &amp;lt;math&amp;gt;M*c^2*i&amp;lt;/math&amp;gt;. Такая сложность получается за счет распараллеливания на каждом ярусе &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; операций. Иерархическая структура параллелизма подробно описана в [[#Информационный граф|п.1.7]].&lt;br /&gt;
&lt;br /&gt;
В алгоритме не возникает скошенного параллелизма.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Входные данные алгоритма: набор векторов &amp;lt;math&amp;gt;x_i&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i = 1,...,M&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
* Объем входных данных: &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt; , [количество наблюдений * размерность].&lt;br /&gt;
* Выходные данные алгоритма: матрица вероятностей принадлежности векторов кластерам &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Объем выходных данных: &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt; , [количество наблюдений * количество кластеров].&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной сложности: &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;&lt;br /&gt;
* Вычислительная мощность: &amp;lt;math&amp;gt;{dc^2i} \over {c+d}&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Устойчивость: алгоритм не является устойчивым, поэтому существует много исследований о том, как первоначально выбрать параметры кластеризации.&lt;br /&gt;
* Сбалансированность: в данном алгоритме операция умножения доминирует над операцией сложения. Операции между параллельными ветвями сбалансированы.&lt;br /&gt;
* Детерминированность: алгоритм не является детерминированным, так как матрица нечеткого разбиение генерируется произвольно.&lt;br /&gt;
* Степень исхода вершины информационного графа (для одной итерации): 2. Если выходные данные пошли на следующую итерацию: 3.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма = &lt;br /&gt;
&lt;br /&gt;
==Особенности реализации последовательного алгоритма==&lt;br /&gt;
&lt;br /&gt;
==Локальность данных и вычислений==&lt;br /&gt;
&lt;br /&gt;
==Возможные способы и особенности параллельной реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
Проведём исследование масштабируемости параллельной реализации нечеткого алгоритма С-средних. &lt;br /&gt;
Исследование проводилось на суперкомпьютере &amp;quot;Ломоносов&amp;quot;&amp;lt;ref name=&amp;quot;Lom&amp;quot;&amp;gt;Воеводин Вл., Жуматий С., Соболев С., Антонов А., Брызгалов П., Никитенко Д., Стефанов К., Воеводин Вад. Практика суперкомпьютера «Ломоносов» // Открытые системы, 2012, N 7, С. 36-39.&amp;lt;/ref&amp;gt; [http://parallel.ru/cluster Суперкомпьютерного комплекса Московского университета]. &lt;br /&gt;
Была исследована собственная параллельная реализация алгоритма, написанная на языке C++ с использованием стандарта MPI. Сборка программы производилась при помощи компилятора компании Intel версии 13.1.0 с использованием библиотеки intelMPI версии 4.1.0 . Расчеты проводились в разделе test на узлах со следующими характеристиками: количество GPU - 0, количество ядер - 8 ядер архитектуры x86, количество памяти - 12 Гб.&lt;br /&gt;
&lt;br /&gt;
Набор и границы значений изменяемых [[Глоссарий#Параметры запуска|параметров запуска]] реализации алгоритма: &lt;br /&gt;
&lt;br /&gt;
*	число процессоров [1 : 128];&lt;br /&gt;
*	размер матрицы [10000 : 80000].&lt;br /&gt;
&lt;br /&gt;
В результате проведённых экспериментов был получен следующий диапазон [[Глоссарий#Эффективность реализации|эффективности реализации]] алгоритма:&lt;br /&gt;
&lt;br /&gt;
*	минимальная эффективность реализации 0,33%;&lt;br /&gt;
*	максимальная эффективность реализации 9,4%.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
На следующих рисунках приведены графики [[Глоссарий#Производительность|производительности]] и  [[Глоссарий#Эффективность реализации|эффективности]] выбранной реализации в зависимости от изменяемых параметров запуска.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[file: FuzzyCMeansPerformance.png |thumb|center|700px|Рисунок 1. Параллельная реализация нечеткого алгоритма С-средних. Изменение производительности в зависимости от числа процессоров и размера матрицы.]]&lt;br /&gt;
[[file: FuzzyCMeansEfficiency2.png|thumb|center|700px|Рисунок 2. Параллельная реализация нечеткого алгоритма С-средних. Изменение эффективности реализации в зависимости от числа процессоров и размера матрицы.]]&lt;br /&gt;
&lt;br /&gt;
Построим оценки масштабируемости выбранной реализации нечеткого алгоритма С-средних:&lt;br /&gt;
*	По числу процессов: 0.007. При увеличении числа процессов эффективность на рассмотренной области изменений параметров запуска увеличивается.&lt;br /&gt;
*	По размеру задачи: -0.0016. При увеличении размера задачи эффективность уменьшается. &lt;br /&gt;
*	По двум направлениям: 0,000077. При рассмотрении увеличения как вычислительной сложности, так и числа процессов на всей рассмотренной области значений эффективность увеличивается, однако скорость увеличения эффективности небольшая.&lt;br /&gt;
&lt;br /&gt;
Была использована следующая реализация алгоритма. &lt;br /&gt;
&lt;br /&gt;
    #include &amp;lt;mpi.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;iostream&amp;gt;&lt;br /&gt;
    #include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;math.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;string.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;time.h&amp;gt;&lt;br /&gt;
    using namespace std;&lt;br /&gt;
    double **x; //input matrix of size (n x x_dim)&lt;br /&gt;
    int n;&lt;br /&gt;
    int x_dim;&lt;br /&gt;
    double **centroids; //cluster centroids matrix of size (n_cluster x x_dim)&lt;br /&gt;
    int n_cluster; // number of clusters&lt;br /&gt;
    double **w; //probability matrix of size (n x n_cluster)&lt;br /&gt;
    double **dist; //distances matrix of size (n x n_cluster)&lt;br /&gt;
    double eps; //max error&lt;br /&gt;
    double m; //parameter of algo&lt;br /&gt;
    int max_iter; // max num of iterations&lt;br /&gt;
    double **num;&lt;br /&gt;
    double *den;&lt;br /&gt;
    double *allden;&lt;br /&gt;
    double *err;&lt;br /&gt;
    double *total_err;&lt;br /&gt;
    int rank, size;&lt;br /&gt;
    double ** generateZerosMatrix(int r, int c){&lt;br /&gt;
        double ** arr = new double* [r];&lt;br /&gt;
        for (int i = 0; i &amp;lt; r; ++i){&lt;br /&gt;
            arr[i] = new double[c]();&lt;br /&gt;
        }&lt;br /&gt;
        return arr;&lt;br /&gt;
    }&lt;br /&gt;
    int generate_data()&lt;br /&gt;
    {&lt;br /&gt;
        //generate matrix&lt;br /&gt;
        x = generateZerosMatrix(n, x_dim);&lt;br /&gt;
        centroids = generateZerosMatrix(n_cluster, x_dim);&lt;br /&gt;
        w = generateZerosMatrix(n, n_cluster);&lt;br /&gt;
        dist = generateZerosMatrix(n, n_cluster);&lt;br /&gt;
        num = generateZerosMatrix(n_cluster, x_dim);&lt;br /&gt;
        //generate vectors&lt;br /&gt;
        den = new double [n_cluster]();&lt;br /&gt;
        allden = new double [n_cluster]();&lt;br /&gt;
        //for stopping algorithm&lt;br /&gt;
        err = new double;&lt;br /&gt;
        total_err = new double;&lt;br /&gt;
        srand(time(0));&lt;br /&gt;
        //initialize w randomly with restrictions&lt;br /&gt;
        for (int i = 0; i &amp;lt; n; ++i){&lt;br /&gt;
            double sum = 0;&lt;br /&gt;
            for (int j = 0; j &amp;lt; n_cluster; ++j){&lt;br /&gt;
                w[i][j] = rand();&lt;br /&gt;
                sum += w[i][j];&lt;br /&gt;
            }&lt;br /&gt;
            for (int j = 0; j &amp;lt; n_cluster; ++j){&lt;br /&gt;
                w[i][j] /= sum;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        //initialize x randomly&lt;br /&gt;
        for (int i = 0; i &amp;lt; n; ++i)&lt;br /&gt;
            for (int j = 0; j &amp;lt; x_dim; ++j)&lt;br /&gt;
                x[i][j] = rand();&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
    double make_iteration() {&lt;br /&gt;
        // calculate centroids centers&lt;br /&gt;
        for (int i = rank; i &amp;lt; n; i+=size)&lt;br /&gt;
            for (int j = 0; j &amp;lt; n_cluster; ++j){&lt;br /&gt;
                double mu = pow(w[i][j], m);&lt;br /&gt;
                den[j] += mu;&lt;br /&gt;
                for (int k = 0; k &amp;lt; x_dim; ++k)&lt;br /&gt;
                    num[j][k] = mu * x[i][k];&lt;br /&gt;
            }&lt;br /&gt;
        MPI_Allreduce(den, allden, n_cluster, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);&lt;br /&gt;
        for (int j=0; j &amp;lt; n_cluster; ++j)&lt;br /&gt;
            MPI_Allreduce(num[j], centroids[j], x_dim, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);&lt;br /&gt;
        for (int i = 0; i &amp;lt; n_cluster; ++i)&lt;br /&gt;
            for (int j = 0; j &amp;lt; x_dim; ++j)&lt;br /&gt;
                centroids[i][j] /= allden[i];&lt;br /&gt;
        // calculate distances and probabilities, check stop conditions&lt;br /&gt;
        double err = 0.0;&lt;br /&gt;
        for (int i = rank; i &amp;lt; n; i+=size)&lt;br /&gt;
            for (int j = 0; j &amp;lt; n_cluster; ++j){&lt;br /&gt;
                for (int k = 0; k &amp;lt; x_dim; ++k)&lt;br /&gt;
                    dist[i][j] += (x[i][k] - centroids[j][k]) * (x[i][k] - centroids[j][k]);&lt;br /&gt;
                double w_prev = w[i][j];&lt;br /&gt;
                for (int k = 0; k &amp;lt; n_cluster; ++k)&lt;br /&gt;
                    w[i][j] += dist[i][j] / dist[i][k];&lt;br /&gt;
                w[i][j] = 1.0 / pow(w[i][j], 1.0 / (m - 1));&lt;br /&gt;
                err = fmax(err, abs(w_prev - w[i][j]));&lt;br /&gt;
            }&lt;br /&gt;
        return err;&lt;br /&gt;
    }&lt;br /&gt;
    int FCM(){&lt;br /&gt;
        *total_err = eps+1;&lt;br /&gt;
        int cur_iter = 0;&lt;br /&gt;
        while (cur_iter &amp;lt; max_iter &amp;amp;&amp;amp; *total_err &amp;gt; eps){&lt;br /&gt;
            *err = make_iteration();&lt;br /&gt;
            MPI_Allreduce(err, total_err, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);&lt;br /&gt;
            cur_iter++;&lt;br /&gt;
        }&lt;br /&gt;
        return cur_iter;&lt;br /&gt;
    }&lt;br /&gt;
    void clearMatrix(double ** matr, int r, int c){&lt;br /&gt;
        for (int i = 0; i &amp;lt; r; ++i){&lt;br /&gt;
            delete [] matr[i];&lt;br /&gt;
        }&lt;br /&gt;
        delete [] matr;&lt;br /&gt;
    }&lt;br /&gt;
    int memory_free(){&lt;br /&gt;
        clearMatrix(x, n, x_dim);&lt;br /&gt;
        clearMatrix(centroids, n_cluster, x_dim);&lt;br /&gt;
        clearMatrix(w, n_cluster, n);&lt;br /&gt;
        clearMatrix(num, n_cluster, x_dim);&lt;br /&gt;
        clearMatrix(dist, n, n_cluster);&lt;br /&gt;
        delete [] den;&lt;br /&gt;
        delete [] allden;&lt;br /&gt;
        delete err;&lt;br /&gt;
        delete total_err;&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
    int main(int argc, char **argv){&lt;br /&gt;
        MPI_Init(&amp;amp;argc, &amp;amp;argv);&lt;br /&gt;
        MPI_Comm_size(MPI_COMM_WORLD, &amp;amp;size);&lt;br /&gt;
        MPI_Comm_rank(MPI_COMM_WORLD, &amp;amp;rank);&lt;br /&gt;
        int n_repeat = strtol(argv[1], NULL, 10);&lt;br /&gt;
        int nx_min = strtol(argv[2], NULL, 10);&lt;br /&gt;
        int nx_max = strtol(argv[3], NULL, 10);&lt;br /&gt;
        int step = strtol(argv[4], NULL, 10);&lt;br /&gt;
        x_dim = strtol(argv[5], NULL, 10);&lt;br /&gt;
        m = strtod(argv[6], NULL);&lt;br /&gt;
        n_cluster = strtol(argv[7], NULL, 10);&lt;br /&gt;
        max_iter = strtol(argv[8], NULL, 10);&lt;br /&gt;
        eps = strtod(argv[9], NULL);&lt;br /&gt;
        //for all input matrix sizes&lt;br /&gt;
        for (n = nx_min; n &amp;lt;= nx_max; n += step){&lt;br /&gt;
            double start, finish, time_elapsed_iter=0;&lt;br /&gt;
            int total_iterations = 0;&lt;br /&gt;
            //repeat for getting mean value&lt;br /&gt;
            for (int i = 0; i &amp;lt; n_repeat; ++i) {&lt;br /&gt;
                generate_data();&lt;br /&gt;
                MPI_Barrier(MPI_COMM_WORLD);&lt;br /&gt;
                start = MPI_Wtime();&lt;br /&gt;
                total_iterations += FCM();&lt;br /&gt;
                finish = MPI_Wtime();&lt;br /&gt;
                memory_free();&lt;br /&gt;
                time_elapsed_iter += (finish-start);&lt;br /&gt;
            }&lt;br /&gt;
            time_elapsed_iter /= total_iterations;&lt;br /&gt;
            if (rank == 0) {&lt;br /&gt;
                cout &amp;lt;&amp;lt; n &amp;lt;&amp;lt; &amp;quot; &amp;quot; &amp;lt;&amp;lt; size &amp;lt;&amp;lt; &amp;quot; &amp;quot; &amp;lt;&amp;lt; time_elapsed_iter &amp;lt;&amp;lt; endl;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        MPI_Finalize();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==Динамические характеристики и эффективность реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
==Выводы для классов архитектур==&lt;br /&gt;
&lt;br /&gt;
==Существующие реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
* Реализация алгоритма на POSTGRESQL: http://num-meth.srcc.msu.ru/zhurnal/tom_2012/pdf/v13r207.pdf&lt;br /&gt;
* Библиотека для MATLAB: http://www.mathworks.com/help/fuzzy/fcm.html (распространяется на коммерческой основе)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=21254</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=21254"/>
		<updated>2016-12-18T20:10:26Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|{{REVISIONUSER}}}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(Mdc^2i)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - количество итераций&lt;br /&gt;
| input_data         = &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt;, [количество наблюдений * размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt;, [количество наблюдений * количество кластеров]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;2i&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]] ([[#Вычислительное ядро алгоритма|1.3]]; [[#Схема реализации последовательного алгоритма|1.5]]; [[#Последовательная сложность алгоритма|1.6]]; [[#Информационный граф|1.7]]; [[#Масштабируемость алгоритма и его реализации|2.4]]; [[#Существующие реализации алгоритма|2.7]]), [[Участник:Yushin|Павел Юшин]] ([[#Общее описание алгоритма|1.1]]; [[#Математическое описание алгоритма|1.2]]; [[#Макроструктура алгоритма|1.4]]; [[#Ресурс параллелизма алгоритма|1.8]]; [[#Входные и выходные данные алгоритма|1.9]]; [[#Свойства алгоритма|1.10]])&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;[http://www.tandfonline.com/doi/abs/10.1080/01969727308546046 | J. C. Dunn. A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters. Journal of Cybernetics, volume 3,1973 - Issue 3, pp 32-57]&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов кластеризации, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров;&amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма не будут отличаться менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;[http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf | Нейский И.М. Классификация и сравнение методов кластеризации.// Интеллектуальные технологии и системы. Сборник учебно-методических работ и статей аспирантов и студентов. – М.: НОК «CLAIM», 2006. – Выпуск 8. – С. 130-142.]&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов, &amp;lt;math&amp;gt;X_i&amp;lt;/math&amp;gt; - набор входных векторов размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве нормы предлагается максимум-норма: &amp;lt;math&amp;gt;||W|| = \max_{i,j} |w_{i,j}|&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M&amp;lt;/math&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;0 &amp;lt; \sum_{i = 1}^M w_{ij} &amp;lt; M, j = 1, ..., c&amp;lt;/math&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда алгоритм принимает следующий вид:&lt;br /&gt;
&lt;br /&gt;
1) Задаем параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
2) Генерируем случайным образом матрицу нечеткого разбиения с учетом условий &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3) Рассчитываем центроиды (центры кластеров): &amp;lt;math&amp;gt;V_j = {{\sum_{i=1}^M w_{ij}^m * X_i} \over {\sum_{i=1}^M w_{ij}^m}}, j = 1, ..., c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Рассчитываем расстояния между объектами &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и центроидами:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_{ij} = {||X_i - V_j||}, i = 1,...,M; j = 1,...,c &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5) Пересчет элементов матрицы разбиения:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} &amp;gt;0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = {{1}\over {{ (\sum_{k=1}^c {{D_{ij}}\over{D_{ik}}} ) }^{2/(m-1)}}}, j = 1,...,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} =0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = \delta_{ij}, j = 1,...,c&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\delta_{ij}&amp;lt;/math&amp;gt; - символ Кронекера&lt;br /&gt;
&lt;br /&gt;
6) Если &amp;lt;math&amp;gt;|| F - F^{*} || &amp;lt; \varepsilon &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;F^{*}&amp;lt;/math&amp;gt; - матрица нечеткого разбиения предыдущей итерации, то идем далее, иначе возвращаемся на пункт 3.&lt;br /&gt;
&lt;br /&gt;
7) Конец.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром алгоритма являются следующие пункты:&lt;br /&gt;
&lt;br /&gt;
* Поиск &amp;lt;math&amp;gt;V_j&amp;lt;/math&amp;gt; - расчет центроидов (пункт 3 алгоритма)&lt;br /&gt;
* Нахождение &amp;lt;math&amp;gt;D_{ij}&amp;lt;/math&amp;gt; - расстояний между объектами (пункт 4 алгоритма)&lt;br /&gt;
* Пересчет &amp;lt;math&amp;gt;w_{ij}&amp;lt;/math&amp;gt; - элементов матрицы разбиения (пункт 5 алгоритма)&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Основные шаги при реализации алгоритма&lt;br /&gt;
*	Генерация случайной матрицы размера &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt;, проверка условий&lt;br /&gt;
*	Расчет центроидов – по сути, скалярное произведение с нормировкой&lt;br /&gt;
*	Расчет расстояний – в общепринятом случае является скалярным произведением&lt;br /&gt;
*	Пересчет матрицы – по сути, скалярное произведение&lt;br /&gt;
*	Проверка условий останова – вычисление нормы&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
    float ** FuzzyCMeans (float** X, c, m, eps){&lt;br /&gt;
        n = X.size();&lt;br /&gt;
        r = X[0].size();&lt;br /&gt;
        centers = generateZeroFill(c, r)&lt;br /&gt;
        Wprev = genetateRandFill(n, c);&lt;br /&gt;
        W = Wprev;&lt;br /&gt;
        while (true){&lt;br /&gt;
            // обновляем центры кластеров &lt;br /&gt;
            for (int i=0; i&amp;lt;c; i++){&lt;br /&gt;
                float * num = new float []();&lt;br /&gt;
                float den = 0;&lt;br /&gt;
                for (int j=0; j&amp;lt;n; j++){&lt;br /&gt;
                    num += pow(W[j][i], m) * X[j];&lt;br /&gt;
                    den+=pow(W[j][i], m);&lt;br /&gt;
                }&lt;br /&gt;
                centers[i] = num / den;&lt;br /&gt;
            }&lt;br /&gt;
            //обновляем вероятности W и считаем расстояние между матрицами W и Wprev&lt;br /&gt;
            float max_diff = 0;&lt;br /&gt;
            for (int i=0; i&amp;lt;n; i++)&lt;br /&gt;
                for (int j=0; j&amp;lt;c; j++){&lt;br /&gt;
                    total = 0;&lt;br /&gt;
                    for (int m=0; m&amp;lt;с; m++)&lt;br /&gt;
                        total += pow(distance(X[i], centers[j]) / distance(X[i], centers[m]), 2/(m-1));&lt;br /&gt;
                    W[i][j] = 1/total;&lt;br /&gt;
                    max_diff = max(abs(Wprev[i][j]-W[i][j]), max_diff);&lt;br /&gt;
                    Wprev[i][j] = W[i][j];&lt;br /&gt;
               }               &lt;br /&gt;
           if (max_diff &amp;lt; eps):                &lt;br /&gt;
                break;&lt;br /&gt;
        }&lt;br /&gt;
        return W;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Последовательная сложность алгоритма состоит из сложности каждой итерации умноженной на их количество. Так как число итераций заранее неизвестно и зависит от входных параметров, рассмотрим сложность на каждой итерации. Наибольшую сложность представляет собой пересчет матрицы, сложность которого &amp;lt;math&amp;gt;O(c^2 nd)&amp;lt;/math&amp;gt; (по сравнению со сложностью &amp;lt;math&amp;gt;O(cnd)&amp;lt;/math&amp;gt; расчета расстояний, вычисления центроидов и проверки условия останова). Итого общая сложность алгоритма &amp;lt;math&amp;gt;O(c^2 ndi)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
Информационный граф представлен на рисунке ниже.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 1, 2, совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз для каждого кластера. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 1&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 2&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m*X_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем вектор размера &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; и матрицу размера &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;. &lt;br /&gt;
Далее совершаем поэлементное сложение векторов и матриц соответственно, а затем делим каждый столбец в матрице на соответствующий элемент в векторе.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй ярус&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 3, 4, 5 также совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 3&#039;&#039;&#039;: обновление значения &amp;lt;math&amp;gt;w_{ij}&amp;lt;/math&amp;gt; по указанной в разделе 1.2 в пункте 5 формуле.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 4&#039;&#039;&#039;: &amp;lt;math&amp;gt;maximum = max(|w_{ij} - w_{ij}^{prev}|, maximum)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 5&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^{prev} = w_{ij}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем число &amp;lt;math&amp;gt;maximum&amp;lt;/math&amp;gt;. Далее находим максимальное значение из полученных величин для каждой ветки. Затем проверяем условие останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:Scheme3.JPG]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельная сложность алгоритма: &amp;lt;math&amp;gt;M*c^2*i&amp;lt;/math&amp;gt;. Такая сложность получается за счет распараллеливания на каждом ярусе &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; операций. Иерархическая структура параллелизма подробно описана в [[#Информационный граф|п.1.7]].&lt;br /&gt;
&lt;br /&gt;
В алгоритме не возникает скошенного параллелизма.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Входные данные алгоритма: набор векторов &amp;lt;math&amp;gt;x_i&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i = 1,...,M&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
* Объем входных данных: &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt; , [количество наблюдений * размерность].&lt;br /&gt;
* Выходные данные алгоритма: матрица вероятностей принадлежности векторов кластерам &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Объем выходных данных: &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt; , [количество наблюдений * количество кластеров].&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной сложности: &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;&lt;br /&gt;
* Вычислительная мощность: &amp;lt;math&amp;gt;{dc^2i} \over {c+d}&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Устойчивость: алгоритм не является устойчивым, поэтому существует много исследований о том, как первоначально выбрать параметры кластеризации.&lt;br /&gt;
* Сбалансированность: в данном алгоритме операция умножения доминирует над операцией сложения. Операции между параллельными ветвями сбалансированы.&lt;br /&gt;
* Детерминированность: алгоритм не является детерминированным, так как матрица нечеткого разбиение генерируется произвольно.&lt;br /&gt;
* Степень исхода вершины информационного графа ( для одной итерации): 2. Если выходные данные пошли на следующую итерацию: 3.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма = &lt;br /&gt;
&lt;br /&gt;
==Особенности реализации последовательного алгоритма==&lt;br /&gt;
&lt;br /&gt;
==Локальность данных и вычислений==&lt;br /&gt;
&lt;br /&gt;
==Возможные способы и особенности параллельной реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
Проведём исследование масштабируемости параллельной реализации нечеткого алгоритма С-средних. &lt;br /&gt;
Исследование проводилось на суперкомпьютере &amp;quot;Ломоносов&amp;quot;&amp;lt;ref name=&amp;quot;Lom&amp;quot;&amp;gt;Воеводин Вл., Жуматий С., Соболев С., Антонов А., Брызгалов П., Никитенко Д., Стефанов К., Воеводин Вад. Практика суперкомпьютера «Ломоносов» // Открытые системы, 2012, N 7, С. 36-39.&amp;lt;/ref&amp;gt; [http://parallel.ru/cluster Суперкомпьютерного комплекса Московского университета]. &lt;br /&gt;
Была исследована собственная параллельная реализация алгоритма, написанная на языке C++ с использованием стандарта MPI. Сборка программы производилась при помощи компилятора компании Intel версии 13.1.0 с использованием библиотеки intelMPI версии 4.1.0 . Расчеты проводились в разделе test на узлах со следующими характеристиками: количество GPU - 0, количество ядер - 8 ядер архитектуры x86, количество памяти - 12 Гб.&lt;br /&gt;
&lt;br /&gt;
Набор и границы значений изменяемых [[Глоссарий#Параметры запуска|параметров запуска]] реализации алгоритма: &lt;br /&gt;
&lt;br /&gt;
*	число процессоров [1 : 128];&lt;br /&gt;
*	размер матрицы [10000 : 80000].&lt;br /&gt;
&lt;br /&gt;
В результате проведённых экспериментов был получен следующий диапазон [[Глоссарий#Эффективность реализации|эффективности реализации]] алгоритма:&lt;br /&gt;
&lt;br /&gt;
*	минимальная эффективность реализации 0,33%;&lt;br /&gt;
*	максимальная эффективность реализации 9,4%.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
На следующих рисунках приведены графики [[Глоссарий#Производительность|производительности]] и  [[Глоссарий#Эффективность реализации|эффективности]] выбранной реализации в зависимости от изменяемых параметров запуска.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[file: FuzzyCMeansPerformance.png |thumb|center|700px|Рисунок 1. Параллельная реализация нечеткого алгоритма С-средних. Изменение производительности в зависимости от числа процессоров и размера матрицы.]]&lt;br /&gt;
[[file: FuzzyCMeansEfficiency2.png|thumb|center|700px|Рисунок 2. Параллельная реализация нечеткого алгоритма С-средних. Изменение эффективности реализации в зависимости от числа процессоров и размера матрицы.]]&lt;br /&gt;
&lt;br /&gt;
Построим оценки масштабируемости выбранной реализации нечеткого алгоритма С-средних:&lt;br /&gt;
*	По числу процессов: 0.007. При увеличении числа процессов эффективность на рассмотренной области изменений параметров запуска увеличивается.&lt;br /&gt;
*	По размеру задачи: -0.0016. При увеличении размера задачи эффективность уменьшается. &lt;br /&gt;
*	По двум направлениям: 0,000077. При рассмотрении увеличения как вычислительной сложности, так и числа процессов на всей рассмотренной области значений эффективность увеличивается, однако скорость увеличения эффективности небольшая.&lt;br /&gt;
&lt;br /&gt;
Была использована следующая реализация алгоритма. &lt;br /&gt;
&lt;br /&gt;
    #include &amp;lt;mpi.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;iostream&amp;gt;&lt;br /&gt;
    #include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;math.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;string.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;time.h&amp;gt;&lt;br /&gt;
    using namespace std;&lt;br /&gt;
    double **x; //input matrix of size (n x x_dim)&lt;br /&gt;
    int n;&lt;br /&gt;
    int x_dim;&lt;br /&gt;
    double **centroids; //cluster centroids matrix of size (n_cluster x x_dim)&lt;br /&gt;
    int n_cluster; // number of clusters&lt;br /&gt;
    double **w; //probability matrix of size (n x n_cluster)&lt;br /&gt;
    double **dist; //distances matrix of size (n x n_cluster)&lt;br /&gt;
    double eps; //max error&lt;br /&gt;
    double m; //parameter of algo&lt;br /&gt;
    int max_iter; // max num of iterations&lt;br /&gt;
    double **num;&lt;br /&gt;
    double *den;&lt;br /&gt;
    double *allden;&lt;br /&gt;
    double *err;&lt;br /&gt;
    double *total_err;&lt;br /&gt;
    int rank, size;&lt;br /&gt;
    double ** generateZerosMatrix(int r, int c){&lt;br /&gt;
        double ** arr = new double* [r];&lt;br /&gt;
        for (int i = 0; i &amp;lt; r; ++i){&lt;br /&gt;
            arr[i] = new double[c]();&lt;br /&gt;
        }&lt;br /&gt;
        return arr;&lt;br /&gt;
    }&lt;br /&gt;
    int generate_data()&lt;br /&gt;
    {&lt;br /&gt;
        //generate matrix&lt;br /&gt;
        x = generateZerosMatrix(n, x_dim);&lt;br /&gt;
        centroids = generateZerosMatrix(n_cluster, x_dim);&lt;br /&gt;
        w = generateZerosMatrix(n, n_cluster);&lt;br /&gt;
        dist = generateZerosMatrix(n, n_cluster);&lt;br /&gt;
        num = generateZerosMatrix(n_cluster, x_dim);&lt;br /&gt;
        //generate vectors&lt;br /&gt;
        den = new double [n_cluster]();&lt;br /&gt;
        allden = new double [n_cluster]();&lt;br /&gt;
        //for stopping algorithm&lt;br /&gt;
        err = new double;&lt;br /&gt;
        total_err = new double;&lt;br /&gt;
        srand(time(0));&lt;br /&gt;
        //initialize w randomly with restrictions&lt;br /&gt;
        for (int i = 0; i &amp;lt; n; ++i){&lt;br /&gt;
            double sum = 0;&lt;br /&gt;
            for (int j = 0; j &amp;lt; n_cluster; ++j){&lt;br /&gt;
                w[i][j] = rand();&lt;br /&gt;
                sum += w[i][j];&lt;br /&gt;
            }&lt;br /&gt;
            for (int j = 0; j &amp;lt; n_cluster; ++j){&lt;br /&gt;
                w[i][j] /= sum;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        //initialize x randomly&lt;br /&gt;
        for (int i = 0; i &amp;lt; n; ++i)&lt;br /&gt;
            for (int j = 0; j &amp;lt; x_dim; ++j)&lt;br /&gt;
                x[i][j] = rand();&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
    double make_iteration() {&lt;br /&gt;
        // calculate centroids centers&lt;br /&gt;
        for (int i = rank; i &amp;lt; n; i+=size)&lt;br /&gt;
            for (int j = 0; j &amp;lt; n_cluster; ++j){&lt;br /&gt;
                double mu = pow(w[i][j], m);&lt;br /&gt;
                den[j] += mu;&lt;br /&gt;
                for (int k = 0; k &amp;lt; x_dim; ++k)&lt;br /&gt;
                    num[j][k] = mu * x[i][k];&lt;br /&gt;
            }&lt;br /&gt;
        MPI_Allreduce(den, allden, n_cluster, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);&lt;br /&gt;
        for (int j=0; j &amp;lt; n_cluster; ++j)&lt;br /&gt;
            MPI_Allreduce(num[j], centroids[j], x_dim, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);&lt;br /&gt;
        for (int i = 0; i &amp;lt; n_cluster; ++i)&lt;br /&gt;
            for (int j = 0; j &amp;lt; x_dim; ++j)&lt;br /&gt;
                centroids[i][j] /= allden[i];&lt;br /&gt;
        // calculate distances and probabilities, check stop conditions&lt;br /&gt;
        double err = 0.0;&lt;br /&gt;
        for (int i = rank; i &amp;lt; n; i+=size)&lt;br /&gt;
            for (int j = 0; j &amp;lt; n_cluster; ++j){&lt;br /&gt;
                for (int k = 0; k &amp;lt; x_dim; ++k)&lt;br /&gt;
                    dist[i][j] += (x[i][k] - centroids[j][k]) * (x[i][k] - centroids[j][k]);&lt;br /&gt;
                double w_prev = w[i][j];&lt;br /&gt;
                for (int k = 0; k &amp;lt; n_cluster; ++k)&lt;br /&gt;
                    w[i][j] += dist[i][j] / dist[i][k];&lt;br /&gt;
                w[i][j] = 1.0 / pow(w[i][j], 1.0 / (m - 1));&lt;br /&gt;
                err = fmax(err, abs(w_prev - w[i][j]));&lt;br /&gt;
            }&lt;br /&gt;
        return err;&lt;br /&gt;
    }&lt;br /&gt;
    int FCM(){&lt;br /&gt;
        *total_err = eps+1;&lt;br /&gt;
        int cur_iter = 0;&lt;br /&gt;
        while (cur_iter &amp;lt; max_iter &amp;amp;&amp;amp; *total_err &amp;gt; eps){&lt;br /&gt;
            *err = make_iteration();&lt;br /&gt;
            MPI_Allreduce(err, total_err, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);&lt;br /&gt;
            cur_iter++;&lt;br /&gt;
        }&lt;br /&gt;
        return cur_iter;&lt;br /&gt;
    }&lt;br /&gt;
    void clearMatrix(double ** matr, int r, int c){&lt;br /&gt;
        for (int i = 0; i &amp;lt; r; ++i){&lt;br /&gt;
            delete [] matr[i];&lt;br /&gt;
        }&lt;br /&gt;
        delete [] matr;&lt;br /&gt;
    }&lt;br /&gt;
    int memory_free(){&lt;br /&gt;
        clearMatrix(x, n, x_dim);&lt;br /&gt;
        clearMatrix(centroids, n_cluster, x_dim);&lt;br /&gt;
        clearMatrix(w, n_cluster, n);&lt;br /&gt;
        clearMatrix(num, n_cluster, x_dim);&lt;br /&gt;
        clearMatrix(dist, n, n_cluster);&lt;br /&gt;
        delete [] den;&lt;br /&gt;
        delete [] allden;&lt;br /&gt;
        delete err;&lt;br /&gt;
        delete total_err;&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
    int main(int argc, char **argv){&lt;br /&gt;
        MPI_Init(&amp;amp;argc, &amp;amp;argv);&lt;br /&gt;
        MPI_Comm_size(MPI_COMM_WORLD, &amp;amp;size);&lt;br /&gt;
        MPI_Comm_rank(MPI_COMM_WORLD, &amp;amp;rank);&lt;br /&gt;
        int n_repeat = strtol(argv[1], NULL, 10);&lt;br /&gt;
        int nx_min = strtol(argv[2], NULL, 10);&lt;br /&gt;
        int nx_max = strtol(argv[3], NULL, 10);&lt;br /&gt;
        int step = strtol(argv[4], NULL, 10);&lt;br /&gt;
        x_dim = strtol(argv[5], NULL, 10);&lt;br /&gt;
        m = strtod(argv[6], NULL);&lt;br /&gt;
        n_cluster = strtol(argv[7], NULL, 10);&lt;br /&gt;
        max_iter = strtol(argv[8], NULL, 10);&lt;br /&gt;
        eps = strtod(argv[9], NULL);&lt;br /&gt;
        //for all input matrix sizes&lt;br /&gt;
        for (n = nx_min; n &amp;lt;= nx_max; n += step){&lt;br /&gt;
            double start, finish, time_elapsed_iter=0;&lt;br /&gt;
            int total_iterations = 0;&lt;br /&gt;
            //repeat for getting mean value&lt;br /&gt;
            for (int i = 0; i &amp;lt; n_repeat; ++i) {&lt;br /&gt;
                generate_data();&lt;br /&gt;
                MPI_Barrier(MPI_COMM_WORLD);&lt;br /&gt;
                start = MPI_Wtime();&lt;br /&gt;
                total_iterations += FCM();&lt;br /&gt;
                finish = MPI_Wtime();&lt;br /&gt;
                memory_free();&lt;br /&gt;
                time_elapsed_iter += (finish-start);&lt;br /&gt;
            }&lt;br /&gt;
            time_elapsed_iter /= total_iterations;&lt;br /&gt;
            if (rank == 0) {&lt;br /&gt;
                cout &amp;lt;&amp;lt; n &amp;lt;&amp;lt; &amp;quot; &amp;quot; &amp;lt;&amp;lt; size &amp;lt;&amp;lt; &amp;quot; &amp;quot; &amp;lt;&amp;lt; time_elapsed_iter &amp;lt;&amp;lt; endl;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        MPI_Finalize();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==Динамические характеристики и эффективность реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
==Выводы для классов архитектур==&lt;br /&gt;
&lt;br /&gt;
==Существующие реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
* Реализация алгоритма на POSTGRESQL: http://num-meth.srcc.msu.ru/zhurnal/tom_2012/pdf/v13r207.pdf&lt;br /&gt;
* Библиотека для MATLAB: http://www.mathworks.com/help/fuzzy/fcm.html (распространяется на коммерческой основе)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=21252</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=21252"/>
		<updated>2016-12-18T20:03:19Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|{{REVISIONUSER}}}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(Mdc^2i)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - количество итераций&lt;br /&gt;
| input_data         = &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt;, [количество наблюдений * размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt;, [количество наблюдений * количество кластеров]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;2i&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]] ([[#Вычислительное ядро алгоритма|1.3]]; [[#Схема реализации последовательного алгоритма|1.5]]; [[#Последовательная сложность алгоритма|1.6]]; [[#Информационный граф|1.7]]; [[#Масштабируемость алгоритма и его реализации|2.4]]; [[#Существующие реализации алгоритма|2.7]]), [[Участник:Yushin|Павел Юшин]] ([[#Общее описание алгоритма|1.1]]; [[#Математическое описание алгоритма|1.2]]; [[#Макроструктура алгоритма|1.4]]; [[#Ресурс параллелизма алгоритма|1.8]]; [[#Входные и выходные данные алгоритма|1.9]]; [[#Свойства алгоритма|1.10]])&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;[http://www.tandfonline.com/doi/abs/10.1080/01969727308546046 | J. C. Dunn. A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters. Journal of Cybernetics, volume 3,1973 - Issue 3, pp 32-57]&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов кластеризации, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров;&amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма не будут отличаться менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;[http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf | Нейский И.М. Классификация и сравнение методов кластеризации.// Интеллектуальные технологии и системы. Сборник учебно-методических работ и статей аспирантов и студентов. – М.: НОК «CLAIM», 2006. – Выпуск 8. – С. 130-142.]&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов, &amp;lt;math&amp;gt;X_i&amp;lt;/math&amp;gt; - набор входных векторов размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве нормы предлагается максимум-норма: &amp;lt;math&amp;gt;||W|| = \max_{i,j} |w_{i,j}|&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M&amp;lt;/math&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;0 &amp;lt; \sum_{i = 1}^M w_{ij} &amp;lt; M, j = 1, ..., c&amp;lt;/math&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда алгоритм принимает следующий вид:&lt;br /&gt;
&lt;br /&gt;
1) Задаем параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
2) Генерируем случайным образом матрицу нечеткого разбиения с учетом условий &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3) Рассчитываем центроиды (центры кластеров): &amp;lt;math&amp;gt;V_j = {{\sum_{i=1}^M w_{ij}^m * X_i} \over {\sum_{i=1}^M w_{ij}^m}}, j = 1, ..., c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Рассчитываем расстояния между объектами &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и центроидами:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_{ij} = {||X_i - V_j||}, i = 1,...,M; j = 1,...,c &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5) Пересчет элементов матрицы разбиения:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} &amp;gt;0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = {{1}\over {{ (\sum_{k=1}^c {{D_{ij}}\over{D_{ik}}} ) }^{2/(m-1)}}}, j = 1,...,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} =0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = \delta_{ij}, j = 1,...,c&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\delta_{ij}&amp;lt;/math&amp;gt; - символ Кронекера&lt;br /&gt;
&lt;br /&gt;
6) Если &amp;lt;math&amp;gt;|| F - F^{*} || &amp;lt; \varepsilon &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;F^{*}&amp;lt;/math&amp;gt; - матрица нечеткого разбиения предыдущей итерации, то идем далее, иначе возвращаемся на пункт 3.&lt;br /&gt;
&lt;br /&gt;
7) Конец.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром алгоритма являются следующие пункты:&lt;br /&gt;
&lt;br /&gt;
* Поиск &amp;lt;math&amp;gt;V_j&amp;lt;/math&amp;gt; - расчет центроидов (пункт 3 алгоритма)&lt;br /&gt;
* Нахождение &amp;lt;math&amp;gt;D_{ij}&amp;lt;/math&amp;gt; - расстояний между объектами (пункт 4 алгоритма)&lt;br /&gt;
* Пересчет &amp;lt;math&amp;gt;w_{ij}&amp;lt;/math&amp;gt; - элементов матрицы разбиения (пункт 5 алгоритма)&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Основные шаги при реализации алгоритма&lt;br /&gt;
*	Генерация случайной матрицы размера &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt;, проверка условий&lt;br /&gt;
*	Расчет центроидов – по сути, скалярное произведение с нормировкой&lt;br /&gt;
*	Расчет расстояний – в общепринятом случае является скалярным произведением&lt;br /&gt;
*	Пересчет матрицы – по сути, скалярное произведение&lt;br /&gt;
*	Проверка условий останова – вычисление нормы&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
    float ** FuzzyCMeans (float** X, c, m, eps){&lt;br /&gt;
        n = X.size();&lt;br /&gt;
        r = X[0].size();&lt;br /&gt;
        centers = generateZeroFill(c, r)&lt;br /&gt;
        Wprev = genetateRandFill(n, c);&lt;br /&gt;
        W = Wprev;&lt;br /&gt;
        while (true){&lt;br /&gt;
            // обновляем центры кластеров &lt;br /&gt;
            for (int i=0; i&amp;lt;c; i++){&lt;br /&gt;
                float * num = new float []();&lt;br /&gt;
                float den = 0;&lt;br /&gt;
                for (int j=0; j&amp;lt;n; j++){&lt;br /&gt;
                    num += pow(W[j][i], m) * X[j];&lt;br /&gt;
                    den+=pow(W[j][i], m);&lt;br /&gt;
                }&lt;br /&gt;
                centers[i] = num / den;&lt;br /&gt;
            }&lt;br /&gt;
            //обновляем вероятности W и считаем расстояние между матрицами W и Wprev&lt;br /&gt;
            float max_diff = 0;&lt;br /&gt;
            for (int i=0; i&amp;lt;n; i++)&lt;br /&gt;
                for (int j=0; j&amp;lt;c; j++){&lt;br /&gt;
                    total = 0;&lt;br /&gt;
                    for (int m=0; m&amp;lt;с; m++)&lt;br /&gt;
                        total += pow(distance(X[i], centers[j]) / distance(X[i], centers[m]), 2/(m-1));&lt;br /&gt;
                    W[i][j] = 1/total;&lt;br /&gt;
                    max_diff = max(abs(Wprev[i][j]-W[i][j]), max_diff);&lt;br /&gt;
                    Wprev[i][j] = W[i][j];&lt;br /&gt;
               }               &lt;br /&gt;
           if (max_diff &amp;lt; eps):                &lt;br /&gt;
                break;&lt;br /&gt;
        }&lt;br /&gt;
        return W;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Последовательная сложность алгоритма состоит из сложности каждой итерации умноженной на их количество. Так как число итераций заранее неизвестно и зависит от входных параметров, рассмотрим сложность на каждой итерации. Наибольшую сложность представляет собой пересчет матрицы, сложность которого &amp;lt;math&amp;gt;O(c^2 nd)&amp;lt;/math&amp;gt; (по сравнению со сложностью &amp;lt;math&amp;gt;O(cnd)&amp;lt;/math&amp;gt; расчета расстояний, вычисления центроидов и проверки условия останова). Итого общая сложность алгоритма &amp;lt;math&amp;gt;O(c^2 ndi)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
Информационный граф представлен на рисунке ниже.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 1, 2, совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз для каждого кластера. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 1&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 2&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m*X_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем вектор размера &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; и матрицу размера &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;. &lt;br /&gt;
Далее совершаем поэлементное сложение векторов и матриц соответственно, а затем делим каждый столбец в матрице на соответствующий элемент в векторе.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй ярус&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 3, 4, 5 также совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 3&#039;&#039;&#039;: обновление значения &amp;lt;math&amp;gt;w_{ij}&amp;lt;/math&amp;gt; по указанной в разделе 1.2 в пункте 5 формуле.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 4&#039;&#039;&#039;: &amp;lt;math&amp;gt;maximum = max(|w_{ij} - w_{ij}^{prev}|, maximum)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 5&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^{prev} = w_{ij}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем число &amp;lt;math&amp;gt;maximum&amp;lt;/math&amp;gt;. Далее находим максимальное значение из полученных величин для каждой ветки. Затем проверяем условие останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:Scheme3.JPG]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельная сложность алгоритма: &amp;lt;math&amp;gt;M*c^2*i&amp;lt;/math&amp;gt;. Такая сложность получается за счет распараллеливания на каждом ярусе &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; операций. Иерархическая структура параллелизма подробно описана в [[#Информационный граф|п.1.7]].&lt;br /&gt;
&lt;br /&gt;
В алгоритме не возникает скошенного параллелизма.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Входные данные алгоритма: набор векторов &amp;lt;math&amp;gt;x_i&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i = 1,...,M&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
* Объем входных данных: &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt; , [количество наблюдений * размерность].&lt;br /&gt;
* Выходные данные алгоритма: матрица вероятностей принадлежности векторов кластерам &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Объем выходных данных: &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt; , [количество наблюдений * количество кластеров].&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной формы алгоритма: &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;&lt;br /&gt;
* Вычислительная мощность: &amp;lt;math&amp;gt;{dc^2i} \over {c+d}&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Устойчивость: алгоритм не является устойчивым, поэтому существует много исследований о том, как первоначально выбрать параметры кластеризации.&lt;br /&gt;
* Сбалансированность: в данном алгоритме операция умножения доминирует над операцией сложения. Операции между параллельными ветвями сбалансированны.&lt;br /&gt;
* Детерминированность: алгоритм не является детерминированным, так как матрица нечеткого разбиение генерируется произвольно.&lt;br /&gt;
* Степень исхода вершины информационного графа ( для одной интерации): 2 (3 - с учетом, если выходные данные пошли на следующую итерацию).&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма = &lt;br /&gt;
&lt;br /&gt;
==Особенности реализации последовательного алгоритма==&lt;br /&gt;
&lt;br /&gt;
==Локальность данных и вычислений==&lt;br /&gt;
&lt;br /&gt;
==Возможные способы и особенности параллельной реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
Проведём исследование масштабируемости параллельной реализации нечеткого алгоритма С-средних. &lt;br /&gt;
Исследование проводилось на суперкомпьютере &amp;quot;Ломоносов&amp;quot;&amp;lt;ref name=&amp;quot;Lom&amp;quot;&amp;gt;Воеводин Вл., Жуматий С., Соболев С., Антонов А., Брызгалов П., Никитенко Д., Стефанов К., Воеводин Вад. Практика суперкомпьютера «Ломоносов» // Открытые системы, 2012, N 7, С. 36-39.&amp;lt;/ref&amp;gt; [http://parallel.ru/cluster Суперкомпьютерного комплекса Московского университета]. &lt;br /&gt;
Была исследована собственная параллельная реализация алгоритма, написанная на языке C++ с использованием стандарта MPI. Сборка программы производилась при помощи компилятора компании Intel версии 13.1.0 с использованием библиотеки intelMPI версии 4.1.0 . Расчеты проводились в разделе test на узлах со следующими характеристиками: количество GPU - 0, количество ядер - 8 ядер архитектуры x86, количество памяти - 12 Гб.&lt;br /&gt;
&lt;br /&gt;
Набор и границы значений изменяемых [[Глоссарий#Параметры запуска|параметров запуска]] реализации алгоритма: &lt;br /&gt;
&lt;br /&gt;
*	число процессоров [1 : 128];&lt;br /&gt;
*	размер матрицы [10000 : 80000].&lt;br /&gt;
&lt;br /&gt;
В результате проведённых экспериментов был получен следующий диапазон [[Глоссарий#Эффективность реализации|эффективности реализации]] алгоритма:&lt;br /&gt;
&lt;br /&gt;
*	минимальная эффективность реализации 0,33%;&lt;br /&gt;
*	максимальная эффективность реализации 9,4%.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
На следующих рисунках приведены графики [[Глоссарий#Производительность|производительности]] и  [[Глоссарий#Эффективность реализации|эффективности]] выбранной реализации в зависимости от изменяемых параметров запуска.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[file: FuzzyCMeansPerformance.png |thumb|center|700px|Рисунок 1. Параллельная реализация нечеткого алгоритма С-средних. Изменение производительности в зависимости от числа процессоров и размера матрицы.]]&lt;br /&gt;
[[file: FuzzyCMeansEfficiency2.png|thumb|center|700px|Рисунок 2. Параллельная реализация нечеткого алгоритма С-средних. Изменение эффективности реализации в зависимости от числа процессоров и размера матрицы.]]&lt;br /&gt;
&lt;br /&gt;
Построим оценки масштабируемости выбранной реализации нечеткого алгоритма С-средних:&lt;br /&gt;
*	По числу процессов: 0.007. При увеличении числа процессов эффективность на рассмотренной области изменений параметров запуска увеличивается.&lt;br /&gt;
*	По размеру задачи: -0.0016. При увеличении размера задачи эффективность уменьшается. &lt;br /&gt;
*	По двум направлениям: 0,000077. При рассмотрении увеличения как вычислительной сложности, так и числа процессов на всей рассмотренной области значений эффективность увеличивается, однако скорость увеличения эффективности небольшая.&lt;br /&gt;
&lt;br /&gt;
Была использована следующая реализация алгоритма. &lt;br /&gt;
&lt;br /&gt;
    #include &amp;lt;mpi.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;iostream&amp;gt;&lt;br /&gt;
    #include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;math.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;string.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;time.h&amp;gt;&lt;br /&gt;
    using namespace std;&lt;br /&gt;
    double **x; //input matrix of size (n x x_dim)&lt;br /&gt;
    int n;&lt;br /&gt;
    int x_dim;&lt;br /&gt;
    double **centroids; //cluster centroids matrix of size (n_cluster x x_dim)&lt;br /&gt;
    int n_cluster; // number of clusters&lt;br /&gt;
    double **w; //probability matrix of size (n x n_cluster)&lt;br /&gt;
    double **dist; //distances matrix of size (n x n_cluster)&lt;br /&gt;
    double eps; //max error&lt;br /&gt;
    double m; //parameter of algo&lt;br /&gt;
    int max_iter; // max num of iterations&lt;br /&gt;
    double **num;&lt;br /&gt;
    double *den;&lt;br /&gt;
    double *allden;&lt;br /&gt;
    double *err;&lt;br /&gt;
    double *total_err;&lt;br /&gt;
    int rank, size;&lt;br /&gt;
    double ** generateZerosMatrix(int r, int c){&lt;br /&gt;
        double ** arr = new double* [r];&lt;br /&gt;
        for (int i = 0; i &amp;lt; r; ++i){&lt;br /&gt;
            arr[i] = new double[c]();&lt;br /&gt;
        }&lt;br /&gt;
        return arr;&lt;br /&gt;
    }&lt;br /&gt;
    int generate_data()&lt;br /&gt;
    {&lt;br /&gt;
        //generate matrix&lt;br /&gt;
        x = generateZerosMatrix(n, x_dim);&lt;br /&gt;
        centroids = generateZerosMatrix(n_cluster, x_dim);&lt;br /&gt;
        w = generateZerosMatrix(n, n_cluster);&lt;br /&gt;
        dist = generateZerosMatrix(n, n_cluster);&lt;br /&gt;
        num = generateZerosMatrix(n_cluster, x_dim);&lt;br /&gt;
        //generate vectors&lt;br /&gt;
        den = new double [n_cluster]();&lt;br /&gt;
        allden = new double [n_cluster]();&lt;br /&gt;
        //for stopping algorithm&lt;br /&gt;
        err = new double;&lt;br /&gt;
        total_err = new double;&lt;br /&gt;
        srand(time(0));&lt;br /&gt;
        //initialize w randomly with restrictions&lt;br /&gt;
        for (int i = 0; i &amp;lt; n; ++i){&lt;br /&gt;
            double sum = 0;&lt;br /&gt;
            for (int j = 0; j &amp;lt; n_cluster; ++j){&lt;br /&gt;
                w[i][j] = rand();&lt;br /&gt;
                sum += w[i][j];&lt;br /&gt;
            }&lt;br /&gt;
            for (int j = 0; j &amp;lt; n_cluster; ++j){&lt;br /&gt;
                w[i][j] /= sum;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        //initialize x randomly&lt;br /&gt;
        for (int i = 0; i &amp;lt; n; ++i)&lt;br /&gt;
            for (int j = 0; j &amp;lt; x_dim; ++j)&lt;br /&gt;
                x[i][j] = rand();&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
    double make_iteration() {&lt;br /&gt;
        // calculate centroids centers&lt;br /&gt;
        for (int i = rank; i &amp;lt; n; i+=size)&lt;br /&gt;
            for (int j = 0; j &amp;lt; n_cluster; ++j){&lt;br /&gt;
                double mu = pow(w[i][j], m);&lt;br /&gt;
                den[j] += mu;&lt;br /&gt;
                for (int k = 0; k &amp;lt; x_dim; ++k)&lt;br /&gt;
                    num[j][k] = mu * x[i][k];&lt;br /&gt;
            }&lt;br /&gt;
        MPI_Allreduce(den, allden, n_cluster, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);&lt;br /&gt;
        for (int j=0; j &amp;lt; n_cluster; ++j)&lt;br /&gt;
            MPI_Allreduce(num[j], centroids[j], x_dim, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);&lt;br /&gt;
        for (int i = 0; i &amp;lt; n_cluster; ++i)&lt;br /&gt;
            for (int j = 0; j &amp;lt; x_dim; ++j)&lt;br /&gt;
                centroids[i][j] /= allden[i];&lt;br /&gt;
        // calculate distances and probabilities, check stop conditions&lt;br /&gt;
        double err = 0.0;&lt;br /&gt;
        for (int i = rank; i &amp;lt; n; i+=size)&lt;br /&gt;
            for (int j = 0; j &amp;lt; n_cluster; ++j){&lt;br /&gt;
                for (int k = 0; k &amp;lt; x_dim; ++k)&lt;br /&gt;
                    dist[i][j] += (x[i][k] - centroids[j][k]) * (x[i][k] - centroids[j][k]);&lt;br /&gt;
                double w_prev = w[i][j];&lt;br /&gt;
                for (int k = 0; k &amp;lt; n_cluster; ++k)&lt;br /&gt;
                    w[i][j] += dist[i][j] / dist[i][k];&lt;br /&gt;
                w[i][j] = 1.0 / pow(w[i][j], 1.0 / (m - 1));&lt;br /&gt;
                err = fmax(err, abs(w_prev - w[i][j]));&lt;br /&gt;
            }&lt;br /&gt;
        return err;&lt;br /&gt;
    }&lt;br /&gt;
    int FCM(){&lt;br /&gt;
        *total_err = eps+1;&lt;br /&gt;
        int cur_iter = 0;&lt;br /&gt;
        while (cur_iter &amp;lt; max_iter &amp;amp;&amp;amp; *total_err &amp;gt; eps){&lt;br /&gt;
            *err = make_iteration();&lt;br /&gt;
            MPI_Allreduce(err, total_err, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);&lt;br /&gt;
            cur_iter++;&lt;br /&gt;
        }&lt;br /&gt;
        return cur_iter;&lt;br /&gt;
    }&lt;br /&gt;
    void clearMatrix(double ** matr, int r, int c){&lt;br /&gt;
        for (int i = 0; i &amp;lt; r; ++i){&lt;br /&gt;
            delete [] matr[i];&lt;br /&gt;
        }&lt;br /&gt;
        delete [] matr;&lt;br /&gt;
    }&lt;br /&gt;
    int memory_free(){&lt;br /&gt;
        clearMatrix(x, n, x_dim);&lt;br /&gt;
        clearMatrix(centroids, n_cluster, x_dim);&lt;br /&gt;
        clearMatrix(w, n_cluster, n);&lt;br /&gt;
        clearMatrix(num, n_cluster, x_dim);&lt;br /&gt;
        clearMatrix(dist, n, n_cluster);&lt;br /&gt;
        delete [] den;&lt;br /&gt;
        delete [] allden;&lt;br /&gt;
        delete err;&lt;br /&gt;
        delete total_err;&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
    int main(int argc, char **argv){&lt;br /&gt;
        MPI_Init(&amp;amp;argc, &amp;amp;argv);&lt;br /&gt;
        MPI_Comm_size(MPI_COMM_WORLD, &amp;amp;size);&lt;br /&gt;
        MPI_Comm_rank(MPI_COMM_WORLD, &amp;amp;rank);&lt;br /&gt;
        int n_repeat = strtol(argv[1], NULL, 10);&lt;br /&gt;
        int nx_min = strtol(argv[2], NULL, 10);&lt;br /&gt;
        int nx_max = strtol(argv[3], NULL, 10);&lt;br /&gt;
        int step = strtol(argv[4], NULL, 10);&lt;br /&gt;
        x_dim = strtol(argv[5], NULL, 10);&lt;br /&gt;
        m = strtod(argv[6], NULL);&lt;br /&gt;
        n_cluster = strtol(argv[7], NULL, 10);&lt;br /&gt;
        max_iter = strtol(argv[8], NULL, 10);&lt;br /&gt;
        eps = strtod(argv[9], NULL);&lt;br /&gt;
        //for all input matrix sizes&lt;br /&gt;
        for (n = nx_min; n &amp;lt;= nx_max; n += step){&lt;br /&gt;
            double start, finish, time_elapsed_iter=0;&lt;br /&gt;
            int total_iterations = 0;&lt;br /&gt;
            //repeat for getting mean value&lt;br /&gt;
            for (int i = 0; i &amp;lt; n_repeat; ++i) {&lt;br /&gt;
                generate_data();&lt;br /&gt;
                MPI_Barrier(MPI_COMM_WORLD);&lt;br /&gt;
                start = MPI_Wtime();&lt;br /&gt;
                total_iterations += FCM();&lt;br /&gt;
                finish = MPI_Wtime();&lt;br /&gt;
                memory_free();&lt;br /&gt;
                time_elapsed_iter += (finish-start);&lt;br /&gt;
            }&lt;br /&gt;
            time_elapsed_iter /= total_iterations;&lt;br /&gt;
            if (rank == 0) {&lt;br /&gt;
                cout &amp;lt;&amp;lt; n &amp;lt;&amp;lt; &amp;quot; &amp;quot; &amp;lt;&amp;lt; size &amp;lt;&amp;lt; &amp;quot; &amp;quot; &amp;lt;&amp;lt; time_elapsed_iter &amp;lt;&amp;lt; endl;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        MPI_Finalize();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==Динамические характеристики и эффективность реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
==Выводы для классов архитектур==&lt;br /&gt;
&lt;br /&gt;
==Существующие реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
* Реализация алгоритма на POSTGRESQL: http://num-meth.srcc.msu.ru/zhurnal/tom_2012/pdf/v13r207.pdf&lt;br /&gt;
* Библиотека для MATLAB: http://www.mathworks.com/help/fuzzy/fcm.html (распространяется на коммерческой основе)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=21251</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=21251"/>
		<updated>2016-12-18T20:00:53Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|{{REVISIONUSER}}}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(Mdc^2i)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - количество итераций&lt;br /&gt;
| input_data         = &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt;, [количество наблюдений * размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt;, [количество наблюдений * количество кластеров]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;2i&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]] ([[#Вычислительное ядро алгоритма|1.3]]; [[#Схема реализации последовательного алгоритма|1.5]]; [[#Последовательная сложность алгоритма|1.6]]; [[#Информационный граф|1.7]]; [[#Масштабируемость алгоритма и его реализации|2.4]]; [[#Существующие реализации алгоритма|2.7]]), [[Участник:Yushin|Павел Юшин]] ([[#Общее описание алгоритма|1.1]]; [[#Математическое описание алгоритма|1.2]]; [[#Макроструктура алгоритма|1.4]]; [[#Ресурс параллелизма алгоритма|1.8]]; [[#Входные и выходные данные алгоритма|1.9]]; [[#Свойства алгоритма|1.10]])&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;[http://www.tandfonline.com/doi/abs/10.1080/01969727308546046 | J. C. Dunn. A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters. Journal of Cybernetics, volume 3,1973 - Issue 3, pp 32-57]&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов кластеризации, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров;&amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма не будут отличаться менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;[http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf | Нейский И.М. Классификация и сравнение методов кластеризации.// Интеллектуальные технологии и системы. Сборник учебно-методических работ и статей аспирантов и студентов. – М.: НОК «CLAIM», 2006. – Выпуск 8. – С. 130-142.]&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов, &amp;lt;math&amp;gt;X_i&amp;lt;/math&amp;gt; - набор входных векторов размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве нормы предлагается максимум-норм: &amp;lt;math&amp;gt;||W|| = max_i,j |w_i,j|&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M&amp;lt;/math&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;0 &amp;lt; \sum_{i = 1}^M w_{ij} &amp;lt; M, j = 1, ..., c&amp;lt;/math&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда алгоритм принимает следующий вид:&lt;br /&gt;
&lt;br /&gt;
1) Задаем параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
2) Генерируем случайным образом матрицу нечеткого разбиения с учетом условий &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3) Рассчитываем центроиды (центры кластеров): &amp;lt;math&amp;gt;V_j = {{\sum_{i=1}^M w_{ij}^m * X_i} \over {\sum_{i=1}^M w_{ij}^m}}, j = 1, ..., c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Рассчитываем расстояния между объектами &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и центроидами:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_{ij} = {||X_i - V_j||}, i = 1,...,M; j = 1,...,c &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5) Пересчет элементов матрицы разбиения:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} &amp;gt;0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = {{1}\over {{ (\sum_{k=1}^c {{D_{ij}}\over{D_{ik}}} ) }^{2/(m-1)}}}, j = 1,...,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} =0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = \delta_{ij}, j = 1,...,c&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\delta_{ij}&amp;lt;/math&amp;gt; - символ Кронекера&lt;br /&gt;
&lt;br /&gt;
6) Если &amp;lt;math&amp;gt;|| F - F^{*} || &amp;lt; \varepsilon &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;F^{*}&amp;lt;/math&amp;gt; - матрица нечеткого разбиения предыдущей итерации, то идем далее, иначе возвращаемся на пункт 3.&lt;br /&gt;
&lt;br /&gt;
7) Конец.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром алгоритма являются следующие пункты:&lt;br /&gt;
&lt;br /&gt;
* Поиск &amp;lt;math&amp;gt;V_j&amp;lt;/math&amp;gt; - расчет центроидов (пункт 3 алгоритма)&lt;br /&gt;
* Нахождение &amp;lt;math&amp;gt;D_{ij}&amp;lt;/math&amp;gt; - расстояний между объектами (пункт 4 алгоритма)&lt;br /&gt;
* Пересчет &amp;lt;math&amp;gt;w_{ij}&amp;lt;/math&amp;gt; - элементов матрицы разбиения (пункт 5 алгоритма)&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Основные шаги при реализации алгоритма&lt;br /&gt;
*	Генерация случайной матрицы размера &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt;, проверка условий&lt;br /&gt;
*	Расчет центроидов – по сути, скалярное произведение с нормировкой&lt;br /&gt;
*	Расчет расстояний – в общепринятом случае является скалярным произведением&lt;br /&gt;
*	Пересчет матрицы – по сути, скалярное произведение&lt;br /&gt;
*	Проверка условий останова – вычисление нормы&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
    float ** FuzzyCMeans (float** X, c, m, eps){&lt;br /&gt;
        n = X.size();&lt;br /&gt;
        r = X[0].size();&lt;br /&gt;
        centers = generateZeroFill(c, r)&lt;br /&gt;
        Wprev = genetateRandFill(n, c);&lt;br /&gt;
        W = Wprev;&lt;br /&gt;
        while (true){&lt;br /&gt;
            // обновляем центры кластеров &lt;br /&gt;
            for (int i=0; i&amp;lt;c; i++){&lt;br /&gt;
                float * num = new float []();&lt;br /&gt;
                float den = 0;&lt;br /&gt;
                for (int j=0; j&amp;lt;n; j++){&lt;br /&gt;
                    num += pow(W[j][i], m) * X[j];&lt;br /&gt;
                    den+=pow(W[j][i], m);&lt;br /&gt;
                }&lt;br /&gt;
                centers[i] = num / den;&lt;br /&gt;
            }&lt;br /&gt;
            //обновляем вероятности W и считаем расстояние между матрицами W и Wprev&lt;br /&gt;
            float max_diff = 0;&lt;br /&gt;
            for (int i=0; i&amp;lt;n; i++)&lt;br /&gt;
                for (int j=0; j&amp;lt;c; j++){&lt;br /&gt;
                    total = 0;&lt;br /&gt;
                    for (int m=0; m&amp;lt;с; m++)&lt;br /&gt;
                        total += pow(distance(X[i], centers[j]) / distance(X[i], centers[m]), 2/(m-1));&lt;br /&gt;
                    W[i][j] = 1/total;&lt;br /&gt;
                    max_diff = max(abs(Wprev[i][j]-W[i][j]), max_diff);&lt;br /&gt;
                    Wprev[i][j] = W[i][j];&lt;br /&gt;
               }               &lt;br /&gt;
           if (max_diff &amp;lt; eps):                &lt;br /&gt;
                break;&lt;br /&gt;
        }&lt;br /&gt;
        return W;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Последовательная сложность алгоритма состоит из сложности каждой итерации умноженной на их количество. Так как число итераций заранее неизвестно и зависит от входных параметров, рассмотрим сложность на каждой итерации. Наибольшую сложность представляет собой пересчет матрицы, сложность которого &amp;lt;math&amp;gt;O(c^2 nd)&amp;lt;/math&amp;gt; (по сравнению со сложностью &amp;lt;math&amp;gt;O(cnd)&amp;lt;/math&amp;gt; расчета расстояний, вычисления центроидов и проверки условия останова). Итого общая сложность алгоритма &amp;lt;math&amp;gt;O(c^2 ndi)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
Информационный граф представлен на рисунке ниже.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 1, 2, совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз для каждого кластера. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 1&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 2&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m*X_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем вектор размера &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; и матрицу размера &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;. &lt;br /&gt;
Далее совершаем поэлементное сложение векторов и матриц соответственно, а затем делим каждый столбец в матрице на соответствующий элемент в векторе.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй ярус&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 3, 4, 5 также совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 3&#039;&#039;&#039;: обновление значения &amp;lt;math&amp;gt;w_{ij}&amp;lt;/math&amp;gt; по указанной в разделе 1.2 в пункте 5 формуле.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 4&#039;&#039;&#039;: &amp;lt;math&amp;gt;maximum = max(|w_{ij} - w_{ij}^{prev}|, maximum)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 5&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^{prev} = w_{ij}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем число &amp;lt;math&amp;gt;maximum&amp;lt;/math&amp;gt;. Далее находим максимальное значение из полученных величин для каждой ветки. Затем проверяем условие останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:Scheme3.JPG]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельная сложность алгоритма: &amp;lt;math&amp;gt;M*c^2*i&amp;lt;/math&amp;gt;. Такая сложность получается за счет распараллеливания на каждом ярусе &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; операций. Иерархическая структура параллелизма подробно описана в [[#Информационный граф|п.1.7]].&lt;br /&gt;
&lt;br /&gt;
В алгоритме не возникает скошенного параллелизма.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Входные данные алгоритма: набор векторов &amp;lt;math&amp;gt;x_i&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i = 1,...,M&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
* Объем входных данных: &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt; , [количество наблюдений * размерность].&lt;br /&gt;
* Выходные данные алгоритма: матрица вероятностей принадлежности векторов кластерам &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Объем выходных данных: &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt; , [количество наблюдений * количество кластеров].&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной формы алгоритма: &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;&lt;br /&gt;
* Вычислительная мощность: &amp;lt;math&amp;gt;{dc^2i} \over {c+d}&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Устойчивость: алгоритм не является устойчивым, поэтому существует много исследований о том, как первоначально выбрать параметры кластеризации.&lt;br /&gt;
* Сбалансированность: в данном алгоритме операция умножения доминирует над операцией сложения. Операции между параллельными ветвями сбалансированны.&lt;br /&gt;
* Детерминированность: алгоритм не является детерминированным, так как матрица нечеткого разбиение генерируется произвольно.&lt;br /&gt;
* Степень исхода вершины информационного графа ( для одной интерации): 2 (3 - с учетом, если выходные данные пошли на следующую итерацию).&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма = &lt;br /&gt;
&lt;br /&gt;
==Особенности реализации последовательного алгоритма==&lt;br /&gt;
&lt;br /&gt;
==Локальность данных и вычислений==&lt;br /&gt;
&lt;br /&gt;
==Возможные способы и особенности параллельной реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
Проведём исследование масштабируемости параллельной реализации нечеткого алгоритма С-средних. &lt;br /&gt;
Исследование проводилось на суперкомпьютере &amp;quot;Ломоносов&amp;quot;&amp;lt;ref name=&amp;quot;Lom&amp;quot;&amp;gt;Воеводин Вл., Жуматий С., Соболев С., Антонов А., Брызгалов П., Никитенко Д., Стефанов К., Воеводин Вад. Практика суперкомпьютера «Ломоносов» // Открытые системы, 2012, N 7, С. 36-39.&amp;lt;/ref&amp;gt; [http://parallel.ru/cluster Суперкомпьютерного комплекса Московского университета]. &lt;br /&gt;
Была исследована собственная параллельная реализация алгоритма, написанная на языке C++ с использованием стандарта MPI. Сборка программы производилась при помощи компилятора компании Intel версии 13.1.0 с использованием библиотеки intelMPI версии 4.1.0 . Расчеты проводились в разделе test на узлах со следующими характеристиками: количество GPU - 0, количество ядер - 8 ядер архитектуры x86, количество памяти - 12 Гб.&lt;br /&gt;
&lt;br /&gt;
Набор и границы значений изменяемых [[Глоссарий#Параметры запуска|параметров запуска]] реализации алгоритма: &lt;br /&gt;
&lt;br /&gt;
*	число процессоров [1 : 128];&lt;br /&gt;
*	размер матрицы [10000 : 80000].&lt;br /&gt;
&lt;br /&gt;
В результате проведённых экспериментов был получен следующий диапазон [[Глоссарий#Эффективность реализации|эффективности реализации]] алгоритма:&lt;br /&gt;
&lt;br /&gt;
*	минимальная эффективность реализации 0,33%;&lt;br /&gt;
*	максимальная эффективность реализации 9,4%.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
На следующих рисунках приведены графики [[Глоссарий#Производительность|производительности]] и  [[Глоссарий#Эффективность реализации|эффективности]] выбранной реализации в зависимости от изменяемых параметров запуска.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[file: FuzzyCMeansPerformance.png |thumb|center|700px|Рисунок 1. Параллельная реализация нечеткого алгоритма С-средних. Изменение производительности в зависимости от числа процессоров и размера матрицы.]]&lt;br /&gt;
[[file: FuzzyCMeansEfficiency2.png|thumb|center|700px|Рисунок 2. Параллельная реализация нечеткого алгоритма С-средних. Изменение эффективности реализации в зависимости от числа процессоров и размера матрицы.]]&lt;br /&gt;
&lt;br /&gt;
Построим оценки масштабируемости выбранной реализации нечеткого алгоритма С-средних:&lt;br /&gt;
*	По числу процессов: 0.007. При увеличении числа процессов эффективность на рассмотренной области изменений параметров запуска увеличивается.&lt;br /&gt;
*	По размеру задачи: -0.0016. При увеличении размера задачи эффективность уменьшается. &lt;br /&gt;
*	По двум направлениям: 0,000077. При рассмотрении увеличения как вычислительной сложности, так и числа процессов на всей рассмотренной области значений эффективность увеличивается, однако скорость увеличения эффективности небольшая.&lt;br /&gt;
&lt;br /&gt;
Была использована следующая реализация алгоритма. &lt;br /&gt;
&lt;br /&gt;
    #include &amp;lt;mpi.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;iostream&amp;gt;&lt;br /&gt;
    #include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;math.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;string.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;time.h&amp;gt;&lt;br /&gt;
    using namespace std;&lt;br /&gt;
    double **x; //input matrix of size (n x x_dim)&lt;br /&gt;
    int n;&lt;br /&gt;
    int x_dim;&lt;br /&gt;
    double **centroids; //cluster centroids matrix of size (n_cluster x x_dim)&lt;br /&gt;
    int n_cluster; // number of clusters&lt;br /&gt;
    double **w; //probability matrix of size (n x n_cluster)&lt;br /&gt;
    double **dist; //distances matrix of size (n x n_cluster)&lt;br /&gt;
    double eps; //max error&lt;br /&gt;
    double m; //parameter of algo&lt;br /&gt;
    int max_iter; // max num of iterations&lt;br /&gt;
    double **num;&lt;br /&gt;
    double *den;&lt;br /&gt;
    double *allden;&lt;br /&gt;
    double *err;&lt;br /&gt;
    double *total_err;&lt;br /&gt;
    int rank, size;&lt;br /&gt;
    double ** generateZerosMatrix(int r, int c){&lt;br /&gt;
        double ** arr = new double* [r];&lt;br /&gt;
        for (int i = 0; i &amp;lt; r; ++i){&lt;br /&gt;
            arr[i] = new double[c]();&lt;br /&gt;
        }&lt;br /&gt;
        return arr;&lt;br /&gt;
    }&lt;br /&gt;
    int generate_data()&lt;br /&gt;
    {&lt;br /&gt;
        //generate matrix&lt;br /&gt;
        x = generateZerosMatrix(n, x_dim);&lt;br /&gt;
        centroids = generateZerosMatrix(n_cluster, x_dim);&lt;br /&gt;
        w = generateZerosMatrix(n, n_cluster);&lt;br /&gt;
        dist = generateZerosMatrix(n, n_cluster);&lt;br /&gt;
        num = generateZerosMatrix(n_cluster, x_dim);&lt;br /&gt;
        //generate vectors&lt;br /&gt;
        den = new double [n_cluster]();&lt;br /&gt;
        allden = new double [n_cluster]();&lt;br /&gt;
        //for stopping algorithm&lt;br /&gt;
        err = new double;&lt;br /&gt;
        total_err = new double;&lt;br /&gt;
        srand(time(0));&lt;br /&gt;
        //initialize w randomly with restrictions&lt;br /&gt;
        for (int i = 0; i &amp;lt; n; ++i){&lt;br /&gt;
            double sum = 0;&lt;br /&gt;
            for (int j = 0; j &amp;lt; n_cluster; ++j){&lt;br /&gt;
                w[i][j] = rand();&lt;br /&gt;
                sum += w[i][j];&lt;br /&gt;
            }&lt;br /&gt;
            for (int j = 0; j &amp;lt; n_cluster; ++j){&lt;br /&gt;
                w[i][j] /= sum;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        //initialize x randomly&lt;br /&gt;
        for (int i = 0; i &amp;lt; n; ++i)&lt;br /&gt;
            for (int j = 0; j &amp;lt; x_dim; ++j)&lt;br /&gt;
                x[i][j] = rand();&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
    double make_iteration() {&lt;br /&gt;
        // calculate centroids centers&lt;br /&gt;
        for (int i = rank; i &amp;lt; n; i+=size)&lt;br /&gt;
            for (int j = 0; j &amp;lt; n_cluster; ++j){&lt;br /&gt;
                double mu = pow(w[i][j], m);&lt;br /&gt;
                den[j] += mu;&lt;br /&gt;
                for (int k = 0; k &amp;lt; x_dim; ++k)&lt;br /&gt;
                    num[j][k] = mu * x[i][k];&lt;br /&gt;
            }&lt;br /&gt;
        MPI_Allreduce(den, allden, n_cluster, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);&lt;br /&gt;
        for (int j=0; j &amp;lt; n_cluster; ++j)&lt;br /&gt;
            MPI_Allreduce(num[j], centroids[j], x_dim, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);&lt;br /&gt;
        for (int i = 0; i &amp;lt; n_cluster; ++i)&lt;br /&gt;
            for (int j = 0; j &amp;lt; x_dim; ++j)&lt;br /&gt;
                centroids[i][j] /= allden[i];&lt;br /&gt;
        // calculate distances and probabilities, check stop conditions&lt;br /&gt;
        double err = 0.0;&lt;br /&gt;
        for (int i = rank; i &amp;lt; n; i+=size)&lt;br /&gt;
            for (int j = 0; j &amp;lt; n_cluster; ++j){&lt;br /&gt;
                for (int k = 0; k &amp;lt; x_dim; ++k)&lt;br /&gt;
                    dist[i][j] += (x[i][k] - centroids[j][k]) * (x[i][k] - centroids[j][k]);&lt;br /&gt;
                double w_prev = w[i][j];&lt;br /&gt;
                for (int k = 0; k &amp;lt; n_cluster; ++k)&lt;br /&gt;
                    w[i][j] += dist[i][j] / dist[i][k];&lt;br /&gt;
                w[i][j] = 1.0 / pow(w[i][j], 1.0 / (m - 1));&lt;br /&gt;
                err = fmax(err, abs(w_prev - w[i][j]));&lt;br /&gt;
            }&lt;br /&gt;
        return err;&lt;br /&gt;
    }&lt;br /&gt;
    int FCM(){&lt;br /&gt;
        *total_err = eps+1;&lt;br /&gt;
        int cur_iter = 0;&lt;br /&gt;
        while (cur_iter &amp;lt; max_iter &amp;amp;&amp;amp; *total_err &amp;gt; eps){&lt;br /&gt;
            *err = make_iteration();&lt;br /&gt;
            MPI_Allreduce(err, total_err, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);&lt;br /&gt;
            cur_iter++;&lt;br /&gt;
        }&lt;br /&gt;
        return cur_iter;&lt;br /&gt;
    }&lt;br /&gt;
    void clearMatrix(double ** matr, int r, int c){&lt;br /&gt;
        for (int i = 0; i &amp;lt; r; ++i){&lt;br /&gt;
            delete [] matr[i];&lt;br /&gt;
        }&lt;br /&gt;
        delete [] matr;&lt;br /&gt;
    }&lt;br /&gt;
    int memory_free(){&lt;br /&gt;
        clearMatrix(x, n, x_dim);&lt;br /&gt;
        clearMatrix(centroids, n_cluster, x_dim);&lt;br /&gt;
        clearMatrix(w, n_cluster, n);&lt;br /&gt;
        clearMatrix(num, n_cluster, x_dim);&lt;br /&gt;
        clearMatrix(dist, n, n_cluster);&lt;br /&gt;
        delete [] den;&lt;br /&gt;
        delete [] allden;&lt;br /&gt;
        delete err;&lt;br /&gt;
        delete total_err;&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
    int main(int argc, char **argv){&lt;br /&gt;
        MPI_Init(&amp;amp;argc, &amp;amp;argv);&lt;br /&gt;
        MPI_Comm_size(MPI_COMM_WORLD, &amp;amp;size);&lt;br /&gt;
        MPI_Comm_rank(MPI_COMM_WORLD, &amp;amp;rank);&lt;br /&gt;
        int n_repeat = strtol(argv[1], NULL, 10);&lt;br /&gt;
        int nx_min = strtol(argv[2], NULL, 10);&lt;br /&gt;
        int nx_max = strtol(argv[3], NULL, 10);&lt;br /&gt;
        int step = strtol(argv[4], NULL, 10);&lt;br /&gt;
        x_dim = strtol(argv[5], NULL, 10);&lt;br /&gt;
        m = strtod(argv[6], NULL);&lt;br /&gt;
        n_cluster = strtol(argv[7], NULL, 10);&lt;br /&gt;
        max_iter = strtol(argv[8], NULL, 10);&lt;br /&gt;
        eps = strtod(argv[9], NULL);&lt;br /&gt;
        //for all input matrix sizes&lt;br /&gt;
        for (n = nx_min; n &amp;lt;= nx_max; n += step){&lt;br /&gt;
            double start, finish, time_elapsed_iter=0;&lt;br /&gt;
            int total_iterations = 0;&lt;br /&gt;
            //repeat for getting mean value&lt;br /&gt;
            for (int i = 0; i &amp;lt; n_repeat; ++i) {&lt;br /&gt;
                generate_data();&lt;br /&gt;
                MPI_Barrier(MPI_COMM_WORLD);&lt;br /&gt;
                start = MPI_Wtime();&lt;br /&gt;
                total_iterations += FCM();&lt;br /&gt;
                finish = MPI_Wtime();&lt;br /&gt;
                memory_free();&lt;br /&gt;
                time_elapsed_iter += (finish-start);&lt;br /&gt;
            }&lt;br /&gt;
            time_elapsed_iter /= total_iterations;&lt;br /&gt;
            if (rank == 0) {&lt;br /&gt;
                cout &amp;lt;&amp;lt; n &amp;lt;&amp;lt; &amp;quot; &amp;quot; &amp;lt;&amp;lt; size &amp;lt;&amp;lt; &amp;quot; &amp;quot; &amp;lt;&amp;lt; time_elapsed_iter &amp;lt;&amp;lt; endl;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        MPI_Finalize();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==Динамические характеристики и эффективность реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
==Выводы для классов архитектур==&lt;br /&gt;
&lt;br /&gt;
==Существующие реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
* Реализация алгоритма на POSTGRESQL: http://num-meth.srcc.msu.ru/zhurnal/tom_2012/pdf/v13r207.pdf&lt;br /&gt;
* Библиотека для MATLAB: http://www.mathworks.com/help/fuzzy/fcm.html (распространяется на коммерческой основе)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=21250</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=21250"/>
		<updated>2016-12-18T20:00:32Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|{{REVISIONUSER}}}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(Mdc^2i)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - количество итераций&lt;br /&gt;
| input_data         = &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt;, [количество наблюдений * размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt;, [количество наблюдений * количество кластеров]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;2i&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]] ([[#Вычислительное ядро алгоритма|1.3]]; [[#Схема реализации последовательного алгоритма|1.5]]; [[#Последовательная сложность алгоритма|1.6]]; [[#Информационный граф|1.7]]; [[#Масштабируемость алгоритма и его реализации|2.4]]; [[#Существующие реализации алгоритма|2.7]]), [[Участник:Yushin|Павел Юшин]] ([[#Общее описание алгоритма|1.1]]; [[#Математическое описание алгоритма|1.2]]; [[#Макроструктура алгоритма|1.4]]; [[#Ресурс параллелизма алгоритма|1.8]]; [[#Входные и выходные данные алгоритма|1.9]]; [[#Свойства алгоритма|1.10]])&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;[http://www.tandfonline.com/doi/abs/10.1080/01969727308546046 | J. C. Dunn. A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters. Journal of Cybernetics, volume 3,1973 - Issue 3, pp 32-57]&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов кластеризации, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров;&amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма не будут отличаться менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;[http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf | Нейский И.М. Классификация и сравнение методов кластеризации.// Интеллектуальные технологии и системы. Сборник учебно-методических работ и статей аспирантов и студентов. – М.: НОК «CLAIM», 2006. – Выпуск 8. – С. 130-142.]&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов, &amp;lt;math&amp;gt;X_i&amp;lt;/math&amp;gt; - набор входных векторов размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве нормы предлагается максимум-норм: &amp;lt;math&amp;gt; ||W|| = max_i,j |w_i,j|&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M&amp;lt;/math&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;0 &amp;lt; \sum_{i = 1}^M w_{ij} &amp;lt; M, j = 1, ..., c&amp;lt;/math&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда алгоритм принимает следующий вид:&lt;br /&gt;
&lt;br /&gt;
1) Задаем параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
2) Генерируем случайным образом матрицу нечеткого разбиения с учетом условий &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3) Рассчитываем центроиды (центры кластеров): &amp;lt;math&amp;gt;V_j = {{\sum_{i=1}^M w_{ij}^m * X_i} \over {\sum_{i=1}^M w_{ij}^m}}, j = 1, ..., c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Рассчитываем расстояния между объектами &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и центроидами:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_{ij} = {||X_i - V_j||}, i = 1,...,M; j = 1,...,c &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5) Пересчет элементов матрицы разбиения:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} &amp;gt;0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = {{1}\over {{ (\sum_{k=1}^c {{D_{ij}}\over{D_{ik}}} ) }^{2/(m-1)}}}, j = 1,...,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} =0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = \delta_{ij}, j = 1,...,c&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\delta_{ij}&amp;lt;/math&amp;gt; - символ Кронекера&lt;br /&gt;
&lt;br /&gt;
6) Если &amp;lt;math&amp;gt;|| F - F^{*} || &amp;lt; \varepsilon &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;F^{*}&amp;lt;/math&amp;gt; - матрица нечеткого разбиения предыдущей итерации, то идем далее, иначе возвращаемся на пункт 3.&lt;br /&gt;
&lt;br /&gt;
7) Конец.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром алгоритма являются следующие пункты:&lt;br /&gt;
&lt;br /&gt;
* Поиск &amp;lt;math&amp;gt;V_j&amp;lt;/math&amp;gt; - расчет центроидов (пункт 3 алгоритма)&lt;br /&gt;
* Нахождение &amp;lt;math&amp;gt;D_{ij}&amp;lt;/math&amp;gt; - расстояний между объектами (пункт 4 алгоритма)&lt;br /&gt;
* Пересчет &amp;lt;math&amp;gt;w_{ij}&amp;lt;/math&amp;gt; - элементов матрицы разбиения (пункт 5 алгоритма)&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Основные шаги при реализации алгоритма&lt;br /&gt;
*	Генерация случайной матрицы размера &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt;, проверка условий&lt;br /&gt;
*	Расчет центроидов – по сути, скалярное произведение с нормировкой&lt;br /&gt;
*	Расчет расстояний – в общепринятом случае является скалярным произведением&lt;br /&gt;
*	Пересчет матрицы – по сути, скалярное произведение&lt;br /&gt;
*	Проверка условий останова – вычисление нормы&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
    float ** FuzzyCMeans (float** X, c, m, eps){&lt;br /&gt;
        n = X.size();&lt;br /&gt;
        r = X[0].size();&lt;br /&gt;
        centers = generateZeroFill(c, r)&lt;br /&gt;
        Wprev = genetateRandFill(n, c);&lt;br /&gt;
        W = Wprev;&lt;br /&gt;
        while (true){&lt;br /&gt;
            // обновляем центры кластеров &lt;br /&gt;
            for (int i=0; i&amp;lt;c; i++){&lt;br /&gt;
                float * num = new float []();&lt;br /&gt;
                float den = 0;&lt;br /&gt;
                for (int j=0; j&amp;lt;n; j++){&lt;br /&gt;
                    num += pow(W[j][i], m) * X[j];&lt;br /&gt;
                    den+=pow(W[j][i], m);&lt;br /&gt;
                }&lt;br /&gt;
                centers[i] = num / den;&lt;br /&gt;
            }&lt;br /&gt;
            //обновляем вероятности W и считаем расстояние между матрицами W и Wprev&lt;br /&gt;
            float max_diff = 0;&lt;br /&gt;
            for (int i=0; i&amp;lt;n; i++)&lt;br /&gt;
                for (int j=0; j&amp;lt;c; j++){&lt;br /&gt;
                    total = 0;&lt;br /&gt;
                    for (int m=0; m&amp;lt;с; m++)&lt;br /&gt;
                        total += pow(distance(X[i], centers[j]) / distance(X[i], centers[m]), 2/(m-1));&lt;br /&gt;
                    W[i][j] = 1/total;&lt;br /&gt;
                    max_diff = max(abs(Wprev[i][j]-W[i][j]), max_diff);&lt;br /&gt;
                    Wprev[i][j] = W[i][j];&lt;br /&gt;
               }               &lt;br /&gt;
           if (max_diff &amp;lt; eps):                &lt;br /&gt;
                break;&lt;br /&gt;
        }&lt;br /&gt;
        return W;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Последовательная сложность алгоритма состоит из сложности каждой итерации умноженной на их количество. Так как число итераций заранее неизвестно и зависит от входных параметров, рассмотрим сложность на каждой итерации. Наибольшую сложность представляет собой пересчет матрицы, сложность которого &amp;lt;math&amp;gt;O(c^2 nd)&amp;lt;/math&amp;gt; (по сравнению со сложностью &amp;lt;math&amp;gt;O(cnd)&amp;lt;/math&amp;gt; расчета расстояний, вычисления центроидов и проверки условия останова). Итого общая сложность алгоритма &amp;lt;math&amp;gt;O(c^2 ndi)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
Информационный граф представлен на рисунке ниже.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 1, 2, совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз для каждого кластера. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 1&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 2&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m*X_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем вектор размера &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; и матрицу размера &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;. &lt;br /&gt;
Далее совершаем поэлементное сложение векторов и матриц соответственно, а затем делим каждый столбец в матрице на соответствующий элемент в векторе.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй ярус&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 3, 4, 5 также совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 3&#039;&#039;&#039;: обновление значения &amp;lt;math&amp;gt;w_{ij}&amp;lt;/math&amp;gt; по указанной в разделе 1.2 в пункте 5 формуле.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 4&#039;&#039;&#039;: &amp;lt;math&amp;gt;maximum = max(|w_{ij} - w_{ij}^{prev}|, maximum)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 5&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^{prev} = w_{ij}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем число &amp;lt;math&amp;gt;maximum&amp;lt;/math&amp;gt;. Далее находим максимальное значение из полученных величин для каждой ветки. Затем проверяем условие останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:Scheme3.JPG]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельная сложность алгоритма: &amp;lt;math&amp;gt;M*c^2*i&amp;lt;/math&amp;gt;. Такая сложность получается за счет распараллеливания на каждом ярусе &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; операций. Иерархическая структура параллелизма подробно описана в [[#Информационный граф|п.1.7]].&lt;br /&gt;
&lt;br /&gt;
В алгоритме не возникает скошенного параллелизма.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Входные данные алгоритма: набор векторов &amp;lt;math&amp;gt;x_i&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i = 1,...,M&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
* Объем входных данных: &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt; , [количество наблюдений * размерность].&lt;br /&gt;
* Выходные данные алгоритма: матрица вероятностей принадлежности векторов кластерам &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Объем выходных данных: &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt; , [количество наблюдений * количество кластеров].&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной формы алгоритма: &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;&lt;br /&gt;
* Вычислительная мощность: &amp;lt;math&amp;gt;{dc^2i} \over {c+d}&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Устойчивость: алгоритм не является устойчивым, поэтому существует много исследований о том, как первоначально выбрать параметры кластеризации.&lt;br /&gt;
* Сбалансированность: в данном алгоритме операция умножения доминирует над операцией сложения. Операции между параллельными ветвями сбалансированны.&lt;br /&gt;
* Детерминированность: алгоритм не является детерминированным, так как матрица нечеткого разбиение генерируется произвольно.&lt;br /&gt;
* Степень исхода вершины информационного графа ( для одной интерации): 2 (3 - с учетом, если выходные данные пошли на следующую итерацию).&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма = &lt;br /&gt;
&lt;br /&gt;
==Особенности реализации последовательного алгоритма==&lt;br /&gt;
&lt;br /&gt;
==Локальность данных и вычислений==&lt;br /&gt;
&lt;br /&gt;
==Возможные способы и особенности параллельной реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
Проведём исследование масштабируемости параллельной реализации нечеткого алгоритма С-средних. &lt;br /&gt;
Исследование проводилось на суперкомпьютере &amp;quot;Ломоносов&amp;quot;&amp;lt;ref name=&amp;quot;Lom&amp;quot;&amp;gt;Воеводин Вл., Жуматий С., Соболев С., Антонов А., Брызгалов П., Никитенко Д., Стефанов К., Воеводин Вад. Практика суперкомпьютера «Ломоносов» // Открытые системы, 2012, N 7, С. 36-39.&amp;lt;/ref&amp;gt; [http://parallel.ru/cluster Суперкомпьютерного комплекса Московского университета]. &lt;br /&gt;
Была исследована собственная параллельная реализация алгоритма, написанная на языке C++ с использованием стандарта MPI. Сборка программы производилась при помощи компилятора компании Intel версии 13.1.0 с использованием библиотеки intelMPI версии 4.1.0 . Расчеты проводились в разделе test на узлах со следующими характеристиками: количество GPU - 0, количество ядер - 8 ядер архитектуры x86, количество памяти - 12 Гб.&lt;br /&gt;
&lt;br /&gt;
Набор и границы значений изменяемых [[Глоссарий#Параметры запуска|параметров запуска]] реализации алгоритма: &lt;br /&gt;
&lt;br /&gt;
*	число процессоров [1 : 128];&lt;br /&gt;
*	размер матрицы [10000 : 80000].&lt;br /&gt;
&lt;br /&gt;
В результате проведённых экспериментов был получен следующий диапазон [[Глоссарий#Эффективность реализации|эффективности реализации]] алгоритма:&lt;br /&gt;
&lt;br /&gt;
*	минимальная эффективность реализации 0,33%;&lt;br /&gt;
*	максимальная эффективность реализации 9,4%.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
На следующих рисунках приведены графики [[Глоссарий#Производительность|производительности]] и  [[Глоссарий#Эффективность реализации|эффективности]] выбранной реализации в зависимости от изменяемых параметров запуска.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[file: FuzzyCMeansPerformance.png |thumb|center|700px|Рисунок 1. Параллельная реализация нечеткого алгоритма С-средних. Изменение производительности в зависимости от числа процессоров и размера матрицы.]]&lt;br /&gt;
[[file: FuzzyCMeansEfficiency2.png|thumb|center|700px|Рисунок 2. Параллельная реализация нечеткого алгоритма С-средних. Изменение эффективности реализации в зависимости от числа процессоров и размера матрицы.]]&lt;br /&gt;
&lt;br /&gt;
Построим оценки масштабируемости выбранной реализации нечеткого алгоритма С-средних:&lt;br /&gt;
*	По числу процессов: 0.007. При увеличении числа процессов эффективность на рассмотренной области изменений параметров запуска увеличивается.&lt;br /&gt;
*	По размеру задачи: -0.0016. При увеличении размера задачи эффективность уменьшается. &lt;br /&gt;
*	По двум направлениям: 0,000077. При рассмотрении увеличения как вычислительной сложности, так и числа процессов на всей рассмотренной области значений эффективность увеличивается, однако скорость увеличения эффективности небольшая.&lt;br /&gt;
&lt;br /&gt;
Была использована следующая реализация алгоритма. &lt;br /&gt;
&lt;br /&gt;
    #include &amp;lt;mpi.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;iostream&amp;gt;&lt;br /&gt;
    #include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;math.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;string.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;time.h&amp;gt;&lt;br /&gt;
    using namespace std;&lt;br /&gt;
    double **x; //input matrix of size (n x x_dim)&lt;br /&gt;
    int n;&lt;br /&gt;
    int x_dim;&lt;br /&gt;
    double **centroids; //cluster centroids matrix of size (n_cluster x x_dim)&lt;br /&gt;
    int n_cluster; // number of clusters&lt;br /&gt;
    double **w; //probability matrix of size (n x n_cluster)&lt;br /&gt;
    double **dist; //distances matrix of size (n x n_cluster)&lt;br /&gt;
    double eps; //max error&lt;br /&gt;
    double m; //parameter of algo&lt;br /&gt;
    int max_iter; // max num of iterations&lt;br /&gt;
    double **num;&lt;br /&gt;
    double *den;&lt;br /&gt;
    double *allden;&lt;br /&gt;
    double *err;&lt;br /&gt;
    double *total_err;&lt;br /&gt;
    int rank, size;&lt;br /&gt;
    double ** generateZerosMatrix(int r, int c){&lt;br /&gt;
        double ** arr = new double* [r];&lt;br /&gt;
        for (int i = 0; i &amp;lt; r; ++i){&lt;br /&gt;
            arr[i] = new double[c]();&lt;br /&gt;
        }&lt;br /&gt;
        return arr;&lt;br /&gt;
    }&lt;br /&gt;
    int generate_data()&lt;br /&gt;
    {&lt;br /&gt;
        //generate matrix&lt;br /&gt;
        x = generateZerosMatrix(n, x_dim);&lt;br /&gt;
        centroids = generateZerosMatrix(n_cluster, x_dim);&lt;br /&gt;
        w = generateZerosMatrix(n, n_cluster);&lt;br /&gt;
        dist = generateZerosMatrix(n, n_cluster);&lt;br /&gt;
        num = generateZerosMatrix(n_cluster, x_dim);&lt;br /&gt;
        //generate vectors&lt;br /&gt;
        den = new double [n_cluster]();&lt;br /&gt;
        allden = new double [n_cluster]();&lt;br /&gt;
        //for stopping algorithm&lt;br /&gt;
        err = new double;&lt;br /&gt;
        total_err = new double;&lt;br /&gt;
        srand(time(0));&lt;br /&gt;
        //initialize w randomly with restrictions&lt;br /&gt;
        for (int i = 0; i &amp;lt; n; ++i){&lt;br /&gt;
            double sum = 0;&lt;br /&gt;
            for (int j = 0; j &amp;lt; n_cluster; ++j){&lt;br /&gt;
                w[i][j] = rand();&lt;br /&gt;
                sum += w[i][j];&lt;br /&gt;
            }&lt;br /&gt;
            for (int j = 0; j &amp;lt; n_cluster; ++j){&lt;br /&gt;
                w[i][j] /= sum;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        //initialize x randomly&lt;br /&gt;
        for (int i = 0; i &amp;lt; n; ++i)&lt;br /&gt;
            for (int j = 0; j &amp;lt; x_dim; ++j)&lt;br /&gt;
                x[i][j] = rand();&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
    double make_iteration() {&lt;br /&gt;
        // calculate centroids centers&lt;br /&gt;
        for (int i = rank; i &amp;lt; n; i+=size)&lt;br /&gt;
            for (int j = 0; j &amp;lt; n_cluster; ++j){&lt;br /&gt;
                double mu = pow(w[i][j], m);&lt;br /&gt;
                den[j] += mu;&lt;br /&gt;
                for (int k = 0; k &amp;lt; x_dim; ++k)&lt;br /&gt;
                    num[j][k] = mu * x[i][k];&lt;br /&gt;
            }&lt;br /&gt;
        MPI_Allreduce(den, allden, n_cluster, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);&lt;br /&gt;
        for (int j=0; j &amp;lt; n_cluster; ++j)&lt;br /&gt;
            MPI_Allreduce(num[j], centroids[j], x_dim, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);&lt;br /&gt;
        for (int i = 0; i &amp;lt; n_cluster; ++i)&lt;br /&gt;
            for (int j = 0; j &amp;lt; x_dim; ++j)&lt;br /&gt;
                centroids[i][j] /= allden[i];&lt;br /&gt;
        // calculate distances and probabilities, check stop conditions&lt;br /&gt;
        double err = 0.0;&lt;br /&gt;
        for (int i = rank; i &amp;lt; n; i+=size)&lt;br /&gt;
            for (int j = 0; j &amp;lt; n_cluster; ++j){&lt;br /&gt;
                for (int k = 0; k &amp;lt; x_dim; ++k)&lt;br /&gt;
                    dist[i][j] += (x[i][k] - centroids[j][k]) * (x[i][k] - centroids[j][k]);&lt;br /&gt;
                double w_prev = w[i][j];&lt;br /&gt;
                for (int k = 0; k &amp;lt; n_cluster; ++k)&lt;br /&gt;
                    w[i][j] += dist[i][j] / dist[i][k];&lt;br /&gt;
                w[i][j] = 1.0 / pow(w[i][j], 1.0 / (m - 1));&lt;br /&gt;
                err = fmax(err, abs(w_prev - w[i][j]));&lt;br /&gt;
            }&lt;br /&gt;
        return err;&lt;br /&gt;
    }&lt;br /&gt;
    int FCM(){&lt;br /&gt;
        *total_err = eps+1;&lt;br /&gt;
        int cur_iter = 0;&lt;br /&gt;
        while (cur_iter &amp;lt; max_iter &amp;amp;&amp;amp; *total_err &amp;gt; eps){&lt;br /&gt;
            *err = make_iteration();&lt;br /&gt;
            MPI_Allreduce(err, total_err, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);&lt;br /&gt;
            cur_iter++;&lt;br /&gt;
        }&lt;br /&gt;
        return cur_iter;&lt;br /&gt;
    }&lt;br /&gt;
    void clearMatrix(double ** matr, int r, int c){&lt;br /&gt;
        for (int i = 0; i &amp;lt; r; ++i){&lt;br /&gt;
            delete [] matr[i];&lt;br /&gt;
        }&lt;br /&gt;
        delete [] matr;&lt;br /&gt;
    }&lt;br /&gt;
    int memory_free(){&lt;br /&gt;
        clearMatrix(x, n, x_dim);&lt;br /&gt;
        clearMatrix(centroids, n_cluster, x_dim);&lt;br /&gt;
        clearMatrix(w, n_cluster, n);&lt;br /&gt;
        clearMatrix(num, n_cluster, x_dim);&lt;br /&gt;
        clearMatrix(dist, n, n_cluster);&lt;br /&gt;
        delete [] den;&lt;br /&gt;
        delete [] allden;&lt;br /&gt;
        delete err;&lt;br /&gt;
        delete total_err;&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
    int main(int argc, char **argv){&lt;br /&gt;
        MPI_Init(&amp;amp;argc, &amp;amp;argv);&lt;br /&gt;
        MPI_Comm_size(MPI_COMM_WORLD, &amp;amp;size);&lt;br /&gt;
        MPI_Comm_rank(MPI_COMM_WORLD, &amp;amp;rank);&lt;br /&gt;
        int n_repeat = strtol(argv[1], NULL, 10);&lt;br /&gt;
        int nx_min = strtol(argv[2], NULL, 10);&lt;br /&gt;
        int nx_max = strtol(argv[3], NULL, 10);&lt;br /&gt;
        int step = strtol(argv[4], NULL, 10);&lt;br /&gt;
        x_dim = strtol(argv[5], NULL, 10);&lt;br /&gt;
        m = strtod(argv[6], NULL);&lt;br /&gt;
        n_cluster = strtol(argv[7], NULL, 10);&lt;br /&gt;
        max_iter = strtol(argv[8], NULL, 10);&lt;br /&gt;
        eps = strtod(argv[9], NULL);&lt;br /&gt;
        //for all input matrix sizes&lt;br /&gt;
        for (n = nx_min; n &amp;lt;= nx_max; n += step){&lt;br /&gt;
            double start, finish, time_elapsed_iter=0;&lt;br /&gt;
            int total_iterations = 0;&lt;br /&gt;
            //repeat for getting mean value&lt;br /&gt;
            for (int i = 0; i &amp;lt; n_repeat; ++i) {&lt;br /&gt;
                generate_data();&lt;br /&gt;
                MPI_Barrier(MPI_COMM_WORLD);&lt;br /&gt;
                start = MPI_Wtime();&lt;br /&gt;
                total_iterations += FCM();&lt;br /&gt;
                finish = MPI_Wtime();&lt;br /&gt;
                memory_free();&lt;br /&gt;
                time_elapsed_iter += (finish-start);&lt;br /&gt;
            }&lt;br /&gt;
            time_elapsed_iter /= total_iterations;&lt;br /&gt;
            if (rank == 0) {&lt;br /&gt;
                cout &amp;lt;&amp;lt; n &amp;lt;&amp;lt; &amp;quot; &amp;quot; &amp;lt;&amp;lt; size &amp;lt;&amp;lt; &amp;quot; &amp;quot; &amp;lt;&amp;lt; time_elapsed_iter &amp;lt;&amp;lt; endl;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        MPI_Finalize();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==Динамические характеристики и эффективность реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
==Выводы для классов архитектур==&lt;br /&gt;
&lt;br /&gt;
==Существующие реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
* Реализация алгоритма на POSTGRESQL: http://num-meth.srcc.msu.ru/zhurnal/tom_2012/pdf/v13r207.pdf&lt;br /&gt;
* Библиотека для MATLAB: http://www.mathworks.com/help/fuzzy/fcm.html (распространяется на коммерческой основе)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=21249</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=21249"/>
		<updated>2016-12-18T19:49:52Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|{{REVISIONUSER}}}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(Mdc^2i)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - количество итераций&lt;br /&gt;
| input_data         = &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt;, [количество наблюдений * размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt;, [количество наблюдений * количество кластеров]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;2i&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]] ([[#Вычислительное ядро алгоритма|1.3]]; [[#Схема реализации последовательного алгоритма|1.5]]; [[#Последовательная сложность алгоритма|1.6]]; [[#Информационный граф|1.7]]; [[#Масштабируемость алгоритма и его реализации|2.4]]; [[#Существующие реализации алгоритма|2.7]]), [[Участник:Yushin|Павел Юшин]] ([[#Общее описание алгоритма|1.1]]; [[#Математическое описание алгоритма|1.2]]; [[#Макроструктура алгоритма|1.4]]; [[#Ресурс параллелизма алгоритма|1.8]]; [[#Входные и выходные данные алгоритма|1.9]]; [[#Свойства алгоритма|1.10]])&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;[http://www.tandfonline.com/doi/abs/10.1080/01969727308546046 | J. C. Dunn. A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters. Journal of Cybernetics, volume 3,1973 - Issue 3, pp 32-57]&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов кластеризации, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров;&amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма не будут отличаться менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;[http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf | Нейский И.М. Классификация и сравнение методов кластеризации.// Интеллектуальные технологии и системы. Сборник учебно-методических работ и статей аспирантов и студентов. – М.: НОК «CLAIM», 2006. – Выпуск 8. – С. 130-142.]&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов, &amp;lt;math&amp;gt;X_i&amp;lt;/math&amp;gt; - набор входных векторов размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M&amp;lt;/math&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;0 &amp;lt; \sum_{i = 1}^M w_{ij} &amp;lt; M, j = 1, ..., c&amp;lt;/math&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда алгоритм принимает следующий вид:&lt;br /&gt;
&lt;br /&gt;
1) Задаем параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
2) Генерируем случайным образом матрицу нечеткого разбиения с учетом условий &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3) Рассчитываем центроиды (центры кластеров): &amp;lt;math&amp;gt;V_j = {{\sum_{i=1}^M w_{ij}^m * X_i} \over {\sum_{i=1}^M w_{ij}^m}}, j = 1, ..., c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Рассчитываем расстояния между объектами &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и центроидами:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_{ij} = {||X_i - V_j||}, i = 1,...,M; j = 1,...,c &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5) Пересчет элементов матрицы разбиения:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} &amp;gt;0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = {{1}\over {{ (\sum_{k=1}^c {{D_{ij}}\over{D_{ik}}} ) }^{2/(m-1)}}}, j = 1,...,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} =0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = \delta_{ij}, j = 1,...,c&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\delta_{ij}&amp;lt;/math&amp;gt; - символ Кронекера&lt;br /&gt;
&lt;br /&gt;
6) Если &amp;lt;math&amp;gt;|| F - F^{*} || &amp;lt; \varepsilon &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;F^{*}&amp;lt;/math&amp;gt; - матрица нечеткого разбиения предыдущей итерации, то идем далее, иначе возвращаемся на пункт 3.&lt;br /&gt;
&lt;br /&gt;
7) Конец.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром алгоритма являются следующие пункты:&lt;br /&gt;
&lt;br /&gt;
* Поиск &amp;lt;math&amp;gt;V_j&amp;lt;/math&amp;gt; - расчет центроидов (пункт 3 алгоритма)&lt;br /&gt;
* Нахождение &amp;lt;math&amp;gt;D_{ij}&amp;lt;/math&amp;gt; - расстояний между объектами (пункт 4 алгоритма)&lt;br /&gt;
* Пересчет &amp;lt;math&amp;gt;w_{ij}&amp;lt;/math&amp;gt; - элементов матрицы разбиения (пункт 5 алгоритма)&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Основные шаги при реализации алгоритма&lt;br /&gt;
*	Генерация случайной матрицы размера &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt;, проверка условий&lt;br /&gt;
*	Расчет центроидов – по сути, скалярное произведение с нормировкой&lt;br /&gt;
*	Расчет расстояний – в общепринятом случае является скалярным произведением&lt;br /&gt;
*	Пересчет матрицы – по сути, скалярное произведение&lt;br /&gt;
*	Проверка условий останова – вычисление нормы&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
    float ** FuzzyCMeans (float** X, c, m, eps){&lt;br /&gt;
        n = X.size();&lt;br /&gt;
        r = X[0].size();&lt;br /&gt;
        centers = generateZeroFill(c, r)&lt;br /&gt;
        Wprev = genetateRandFill(n, c);&lt;br /&gt;
        W = Wprev;&lt;br /&gt;
        while (true){&lt;br /&gt;
            // обновляем центры кластеров &lt;br /&gt;
            for (int i=0; i&amp;lt;c; i++){&lt;br /&gt;
                float * num = new float []();&lt;br /&gt;
                float den = 0;&lt;br /&gt;
                for (int j=0; j&amp;lt;n; j++){&lt;br /&gt;
                    num += pow(W[j][i], m) * X[j];&lt;br /&gt;
                    den+=pow(W[j][i], m);&lt;br /&gt;
                }&lt;br /&gt;
                centers[i] = num / den;&lt;br /&gt;
            }&lt;br /&gt;
            //обновляем вероятности W и считаем расстояние между матрицами W и Wprev&lt;br /&gt;
            float max_diff = 0;&lt;br /&gt;
            for (int i=0; i&amp;lt;n; i++)&lt;br /&gt;
                for (int j=0; j&amp;lt;c; j++){&lt;br /&gt;
                    total = 0;&lt;br /&gt;
                    for (int m=0; m&amp;lt;с; m++)&lt;br /&gt;
                        total += pow(distance(X[i], centers[j]) / distance(X[i], centers[m]), 2/(m-1));&lt;br /&gt;
                    W[i][j] = 1/total;&lt;br /&gt;
                    max_diff = max(abs(Wprev[i][j]-W[i][j]), max_diff);&lt;br /&gt;
                    Wprev[i][j] = W[i][j];&lt;br /&gt;
               }               &lt;br /&gt;
           if (max_diff &amp;lt; eps):                &lt;br /&gt;
                break;&lt;br /&gt;
        }&lt;br /&gt;
        return W;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Последовательная сложность алгоритма состоит из сложности каждой итерации умноженной на их количество. Так как число итераций заранее неизвестно и зависит от входных параметров, рассмотрим сложность на каждой итерации. Наибольшую сложность представляет собой пересчет матрицы, сложность которого &amp;lt;math&amp;gt;O(c^2 nd)&amp;lt;/math&amp;gt; (по сравнению со сложностью &amp;lt;math&amp;gt;O(cnd)&amp;lt;/math&amp;gt; расчета расстояний, вычисления центроидов и проверки условия останова). Итого общая сложность алгоритма &amp;lt;math&amp;gt;O(c^2 ndi)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
Информационный граф представлен на рисунке ниже.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 1, 2, совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз для каждого кластера. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 1&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 2&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m*X_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем вектор размера &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; и матрицу размера &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;. &lt;br /&gt;
Далее совершаем поэлементное сложение векторов и матриц соответственно, а затем делим каждый столбец в матрице на соответствующий элемент в векторе.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй ярус&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 3, 4, 5 также совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 3&#039;&#039;&#039;: обновление значения &amp;lt;math&amp;gt;w_{ij}&amp;lt;/math&amp;gt; по указанной в разделе 1.2 в пункте 5 формуле.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 4&#039;&#039;&#039;: &amp;lt;math&amp;gt;maximum = max(|w_{ij} - w_{ij}^{prev}|, maximum)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 5&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^{prev} = w_{ij}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем число &amp;lt;math&amp;gt;maximum&amp;lt;/math&amp;gt;. Далее находим максимальное значение из полученных величин для каждой ветки. Затем проверяем условие останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:Scheme3.JPG]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельная сложность алгоритма: &amp;lt;math&amp;gt;M*c^2*i&amp;lt;/math&amp;gt;. Такая сложность получается за счет распараллеливания на каждом ярусе &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; операций. Иерархическая структура параллелизма подробно описана в [[#Информационный граф|п.1.7]].&lt;br /&gt;
&lt;br /&gt;
В алгоритме не возникает скошенного параллелизма.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Входные данные алгоритма: набор векторов &amp;lt;math&amp;gt;x_i&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i = 1,...,M&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
* Объем входных данных: &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt; , [количество наблюдений * размерность].&lt;br /&gt;
* Выходные данные алгоритма: матрица вероятностей принадлежности векторов кластерам &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Объем выходных данных: &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt; , [количество наблюдений * количество кластеров].&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной формы алгоритма: &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;&lt;br /&gt;
* Вычислительная мощность: &amp;lt;math&amp;gt;{dc^2i} \over {c+d}&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Устойчивость: алгоритм не является устойчивым, поэтому существует много исследований о том, как первоначально выбрать параметры кластеризации.&lt;br /&gt;
* Сбалансированность: в данном алгоритме операция умножения доминирует над операцией сложения. Операции между параллельными ветвями сбалансированны.&lt;br /&gt;
* Детерминированность: алгоритм не является детерминированным, так как матрица нечеткого разбиение генерируется произвольно.&lt;br /&gt;
* Степень исхода вершины информационного графа ( для одной интерации): 2 (3 - с учетом, если выходные данные пошли на следующую итерацию).&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма = &lt;br /&gt;
&lt;br /&gt;
==Особенности реализации последовательного алгоритма==&lt;br /&gt;
&lt;br /&gt;
==Локальность данных и вычислений==&lt;br /&gt;
&lt;br /&gt;
==Возможные способы и особенности параллельной реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
Проведём исследование масштабируемости параллельной реализации нечеткого алгоритма С-средних. &lt;br /&gt;
Исследование проводилось на суперкомпьютере &amp;quot;Ломоносов&amp;quot;&amp;lt;ref name=&amp;quot;Lom&amp;quot;&amp;gt;Воеводин Вл., Жуматий С., Соболев С., Антонов А., Брызгалов П., Никитенко Д., Стефанов К., Воеводин Вад. Практика суперкомпьютера «Ломоносов» // Открытые системы, 2012, N 7, С. 36-39.&amp;lt;/ref&amp;gt; [http://parallel.ru/cluster Суперкомпьютерного комплекса Московского университета]. &lt;br /&gt;
Была исследована собственная параллельная реализация алгоритма, написанная на языке C++ с использованием стандарта MPI. Сборка программы производилась при помощи компилятора компании Intel версии 13.1.0 с использованием библиотеки intelMPI версии 4.1.0 . Расчеты проводились в разделе test на узлах со следующими характеристиками: количество GPU - 0, количество ядер - 8 ядер архитектуры x86, количество памяти - 12 Гб.&lt;br /&gt;
&lt;br /&gt;
Набор и границы значений изменяемых [[Глоссарий#Параметры запуска|параметров запуска]] реализации алгоритма: &lt;br /&gt;
&lt;br /&gt;
*	число процессоров [1 : 128];&lt;br /&gt;
*	размер матрицы [10000 : 80000].&lt;br /&gt;
&lt;br /&gt;
В результате проведённых экспериментов был получен следующий диапазон [[Глоссарий#Эффективность реализации|эффективности реализации]] алгоритма:&lt;br /&gt;
&lt;br /&gt;
*	минимальная эффективность реализации 0,33%;&lt;br /&gt;
*	максимальная эффективность реализации 9,4%.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
На следующих рисунках приведены графики [[Глоссарий#Производительность|производительности]] и  [[Глоссарий#Эффективность реализации|эффективности]] выбранной реализации в зависимости от изменяемых параметров запуска.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[file: FuzzyCMeansPerformance.png |thumb|center|700px|Рисунок 1. Параллельная реализация нечеткого алгоритма С-средних. Изменение производительности в зависимости от числа процессоров и размера матрицы.]]&lt;br /&gt;
[[file: FuzzyCMeansEfficiency2.png|thumb|center|700px|Рисунок 2. Параллельная реализация нечеткого алгоритма С-средних. Изменение эффективности реализации в зависимости от числа процессоров и размера матрицы.]]&lt;br /&gt;
&lt;br /&gt;
Построим оценки масштабируемости выбранной реализации нечеткого алгоритма С-средних:&lt;br /&gt;
*	По числу процессов: 0.007. При увеличении числа процессов эффективность на рассмотренной области изменений параметров запуска увеличивается.&lt;br /&gt;
*	По размеру задачи: -0.0016. При увеличении размера задачи эффективность уменьшается. &lt;br /&gt;
*	По двум направлениям: 0,000077. При рассмотрении увеличения как вычислительной сложности, так и числа процессов на всей рассмотренной области значений эффективность увеличивается, однако скорость увеличения эффективности небольшая.&lt;br /&gt;
&lt;br /&gt;
Была использована следующая реализация алгоритма. &lt;br /&gt;
&lt;br /&gt;
    #include &amp;lt;mpi.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;iostream&amp;gt;&lt;br /&gt;
    #include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;math.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;string.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;time.h&amp;gt;&lt;br /&gt;
    using namespace std;&lt;br /&gt;
    double **x; //input matrix of size (n x x_dim)&lt;br /&gt;
    int n;&lt;br /&gt;
    int x_dim;&lt;br /&gt;
    double **centroids; //cluster centroids matrix of size (n_cluster x x_dim)&lt;br /&gt;
    int n_cluster; // number of clusters&lt;br /&gt;
    double **w; //probability matrix of size (n x n_cluster)&lt;br /&gt;
    double **dist; //distances matrix of size (n x n_cluster)&lt;br /&gt;
    double eps; //max error&lt;br /&gt;
    double m; //parameter of algo&lt;br /&gt;
    int max_iter; // max num of iterations&lt;br /&gt;
    double **num;&lt;br /&gt;
    double *den;&lt;br /&gt;
    double *allden;&lt;br /&gt;
    double *err;&lt;br /&gt;
    double *total_err;&lt;br /&gt;
    int rank, size;&lt;br /&gt;
    double ** generateZerosMatrix(int r, int c){&lt;br /&gt;
        double ** arr = new double* [r];&lt;br /&gt;
        for (int i = 0; i &amp;lt; r; ++i){&lt;br /&gt;
            arr[i] = new double[c]();&lt;br /&gt;
        }&lt;br /&gt;
        return arr;&lt;br /&gt;
    }&lt;br /&gt;
    int generate_data()&lt;br /&gt;
    {&lt;br /&gt;
        //generate matrix&lt;br /&gt;
        x = generateZerosMatrix(n, x_dim);&lt;br /&gt;
        centroids = generateZerosMatrix(n_cluster, x_dim);&lt;br /&gt;
        w = generateZerosMatrix(n, n_cluster);&lt;br /&gt;
        dist = generateZerosMatrix(n, n_cluster);&lt;br /&gt;
        num = generateZerosMatrix(n_cluster, x_dim);&lt;br /&gt;
        //generate vectors&lt;br /&gt;
        den = new double [n_cluster]();&lt;br /&gt;
        allden = new double [n_cluster]();&lt;br /&gt;
        //for stopping algorithm&lt;br /&gt;
        err = new double;&lt;br /&gt;
        total_err = new double;&lt;br /&gt;
        srand(time(0));&lt;br /&gt;
        //initialize w randomly with restrictions&lt;br /&gt;
        for (int i = 0; i &amp;lt; n; ++i){&lt;br /&gt;
            double sum = 0;&lt;br /&gt;
            for (int j = 0; j &amp;lt; n_cluster; ++j){&lt;br /&gt;
                w[i][j] = rand();&lt;br /&gt;
                sum += w[i][j];&lt;br /&gt;
            }&lt;br /&gt;
            for (int j = 0; j &amp;lt; n_cluster; ++j){&lt;br /&gt;
                w[i][j] /= sum;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        //initialize x randomly&lt;br /&gt;
        for (int i = 0; i &amp;lt; n; ++i)&lt;br /&gt;
            for (int j = 0; j &amp;lt; x_dim; ++j)&lt;br /&gt;
                x[i][j] = rand();&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
    double make_iteration() {&lt;br /&gt;
        // calculate centroids centers&lt;br /&gt;
        for (int i = rank; i &amp;lt; n; i+=size)&lt;br /&gt;
            for (int j = 0; j &amp;lt; n_cluster; ++j){&lt;br /&gt;
                double mu = pow(w[i][j], m);&lt;br /&gt;
                den[j] += mu;&lt;br /&gt;
                for (int k = 0; k &amp;lt; x_dim; ++k)&lt;br /&gt;
                    num[j][k] = mu * x[i][k];&lt;br /&gt;
            }&lt;br /&gt;
        MPI_Allreduce(den, allden, n_cluster, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);&lt;br /&gt;
        for (int j=0; j &amp;lt; n_cluster; ++j)&lt;br /&gt;
            MPI_Allreduce(num[j], centroids[j], x_dim, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);&lt;br /&gt;
        for (int i = 0; i &amp;lt; n_cluster; ++i)&lt;br /&gt;
            for (int j = 0; j &amp;lt; x_dim; ++j)&lt;br /&gt;
                centroids[i][j] /= allden[i];&lt;br /&gt;
        // calculate distances and probabilities, check stop conditions&lt;br /&gt;
        double err = 0.0;&lt;br /&gt;
        for (int i = rank; i &amp;lt; n; i+=size)&lt;br /&gt;
            for (int j = 0; j &amp;lt; n_cluster; ++j){&lt;br /&gt;
                for (int k = 0; k &amp;lt; x_dim; ++k)&lt;br /&gt;
                    dist[i][j] += (x[i][k] - centroids[j][k]) * (x[i][k] - centroids[j][k]);&lt;br /&gt;
                double w_prev = w[i][j];&lt;br /&gt;
                for (int k = 0; k &amp;lt; n_cluster; ++k)&lt;br /&gt;
                    w[i][j] += dist[i][j] / dist[i][k];&lt;br /&gt;
                w[i][j] = 1.0 / pow(w[i][j], 1.0 / (m - 1));&lt;br /&gt;
                err = fmax(err, abs(w_prev - w[i][j]));&lt;br /&gt;
            }&lt;br /&gt;
        return err;&lt;br /&gt;
    }&lt;br /&gt;
    int FCM(){&lt;br /&gt;
        *total_err = eps+1;&lt;br /&gt;
        int cur_iter = 0;&lt;br /&gt;
        while (cur_iter &amp;lt; max_iter &amp;amp;&amp;amp; *total_err &amp;gt; eps){&lt;br /&gt;
            *err = make_iteration();&lt;br /&gt;
            MPI_Allreduce(err, total_err, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);&lt;br /&gt;
            cur_iter++;&lt;br /&gt;
        }&lt;br /&gt;
        return cur_iter;&lt;br /&gt;
    }&lt;br /&gt;
    void clearMatrix(double ** matr, int r, int c){&lt;br /&gt;
        for (int i = 0; i &amp;lt; r; ++i){&lt;br /&gt;
            delete [] matr[i];&lt;br /&gt;
        }&lt;br /&gt;
        delete [] matr;&lt;br /&gt;
    }&lt;br /&gt;
    int memory_free(){&lt;br /&gt;
        clearMatrix(x, n, x_dim);&lt;br /&gt;
        clearMatrix(centroids, n_cluster, x_dim);&lt;br /&gt;
        clearMatrix(w, n_cluster, n);&lt;br /&gt;
        clearMatrix(num, n_cluster, x_dim);&lt;br /&gt;
        clearMatrix(dist, n, n_cluster);&lt;br /&gt;
        delete [] den;&lt;br /&gt;
        delete [] allden;&lt;br /&gt;
        delete err;&lt;br /&gt;
        delete total_err;&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
    int main(int argc, char **argv){&lt;br /&gt;
        MPI_Init(&amp;amp;argc, &amp;amp;argv);&lt;br /&gt;
        MPI_Comm_size(MPI_COMM_WORLD, &amp;amp;size);&lt;br /&gt;
        MPI_Comm_rank(MPI_COMM_WORLD, &amp;amp;rank);&lt;br /&gt;
        int n_repeat = strtol(argv[1], NULL, 10);&lt;br /&gt;
        int nx_min = strtol(argv[2], NULL, 10);&lt;br /&gt;
        int nx_max = strtol(argv[3], NULL, 10);&lt;br /&gt;
        int step = strtol(argv[4], NULL, 10);&lt;br /&gt;
        x_dim = strtol(argv[5], NULL, 10);&lt;br /&gt;
        m = strtod(argv[6], NULL);&lt;br /&gt;
        n_cluster = strtol(argv[7], NULL, 10);&lt;br /&gt;
        max_iter = strtol(argv[8], NULL, 10);&lt;br /&gt;
        eps = strtod(argv[9], NULL);&lt;br /&gt;
        //for all input matrix sizes&lt;br /&gt;
        for (n = nx_min; n &amp;lt;= nx_max; n += step){&lt;br /&gt;
            double start, finish, time_elapsed_iter=0;&lt;br /&gt;
            int total_iterations = 0;&lt;br /&gt;
            //repeat for getting mean value&lt;br /&gt;
            for (int i = 0; i &amp;lt; n_repeat; ++i) {&lt;br /&gt;
                generate_data();&lt;br /&gt;
                MPI_Barrier(MPI_COMM_WORLD);&lt;br /&gt;
                start = MPI_Wtime();&lt;br /&gt;
                total_iterations += FCM();&lt;br /&gt;
                finish = MPI_Wtime();&lt;br /&gt;
                memory_free();&lt;br /&gt;
                time_elapsed_iter += (finish-start);&lt;br /&gt;
            }&lt;br /&gt;
            time_elapsed_iter /= total_iterations;&lt;br /&gt;
            if (rank == 0) {&lt;br /&gt;
                cout &amp;lt;&amp;lt; n &amp;lt;&amp;lt; &amp;quot; &amp;quot; &amp;lt;&amp;lt; size &amp;lt;&amp;lt; &amp;quot; &amp;quot; &amp;lt;&amp;lt; time_elapsed_iter &amp;lt;&amp;lt; endl;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        MPI_Finalize();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==Динамические характеристики и эффективность реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
==Выводы для классов архитектур==&lt;br /&gt;
&lt;br /&gt;
==Существующие реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
* Реализация алгоритма на POSTGRESQL: http://num-meth.srcc.msu.ru/zhurnal/tom_2012/pdf/v13r207.pdf&lt;br /&gt;
* Библиотека для MATLAB: http://www.mathworks.com/help/fuzzy/fcm.html (распространяется на коммерческой основе)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=21246</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=21246"/>
		<updated>2016-12-18T19:31:23Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|{{REVISIONUSER}}}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(Mdc^2i)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - количество итераций&lt;br /&gt;
| input_data         = &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt;, [количество наблюдений * размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt;, [количество наблюдений * количество кластеров]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;2i&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]] ([[#Вычислительное ядро алгоритма|1.3]]; [[#Схема реализации последовательного алгоритма|1.5]]; [[#Последовательная сложность алгоритма|1.6]]; [[#Информационный граф|1.7]]; [[#Масштабируемость алгоритма и его реализации|2.4]]; [[#Существующие реализации алгоритма|2.7]]), [[Участник:Yushin|Павел Юшин]] ([[#Общее описание алгоритма|1.1]]; [[#Математическое описание алгоритма|1.2]]; [[#Макроструктура алгоритма|1.4]]; [[#Ресурс параллелизма алгоритма|1.8]]; [[#Входные и выходные данные алгоритма|1.9]]; [[#Свойства алгоритма|1.10]])&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;[http://www.tandfonline.com/doi/abs/10.1080/01969727308546046 | J. C. Dunn. A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters. Journal of Cybernetics, volume 3,1973 - Issue 3, pp 32-57]&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов кластеризации, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров;&amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма не будут отличаться менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;[http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf | Нейский И.М. Классификация и сравнение методов кластеризации.// Интеллектуальные технологии и системы. Сборник учебно-методических работ и статей аспирантов и студентов. – М.: НОК «CLAIM», 2006. – Выпуск 8. – С. 130-142.]&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов, &amp;lt;math&amp;gt;X_i&amp;lt;/math&amp;gt; - набор входных векторов размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M&amp;lt;/math&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;0 &amp;lt; \sum_{i = 1}^M w_{ij} &amp;lt; M, j = 1, ..., c&amp;lt;/math&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда алгоритм принимает следующий вид:&lt;br /&gt;
&lt;br /&gt;
1) Задаем параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
2) Генерируем случайным образом матрицу нечеткого разбиения с учетом условий &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3) Рассчитываем центроиды (центры кластеров): &amp;lt;math&amp;gt;V_j = {{\sum_{i=1}^M w_{ij}^m * X_i} \over {\sum_{i=1}^M w_{ij}^m}}, j = 1, ..., c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Рассчитываем расстояния между объектами &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и центроидами:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_{ij} = {||X_i - V_j||}, i = 1,...,M; j = 1,...,c &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5) Пересчет элементов матрицы разбиения:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} &amp;gt;0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = {{1}\over {{ (\sum_{k=1}^c {{D_{ij}}\over{D_{ik}}} ) }^{2/(m-1)}}}, j = 1,...,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} =0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = \delta_{ij}, j = 1,...,c&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\delta_{ij}&amp;lt;/math&amp;gt; - символ Кронекера&lt;br /&gt;
&lt;br /&gt;
6) Если &amp;lt;math&amp;gt;|| F - F^{*} || &amp;lt; \varepsilon &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;F^{*}&amp;lt;/math&amp;gt; - матрица нечеткого разбиения предыдущей итерации, то идем далее, иначе возвращаемся на пункт 3.&lt;br /&gt;
&lt;br /&gt;
7) Конец.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром алгоритма являются следующие пункты:&lt;br /&gt;
&lt;br /&gt;
* Поиск &amp;lt;math&amp;gt;V_j&amp;lt;/math&amp;gt; - расчет центроидов (пункт 3 алгоритма)&lt;br /&gt;
* Нахождение &amp;lt;math&amp;gt;D_{ij}&amp;lt;/math&amp;gt; - расстояний между объектами (пункт 4 алгоритма)&lt;br /&gt;
* Пересчет &amp;lt;math&amp;gt;w_{ij}&amp;lt;/math&amp;gt; - элементов матрицы разбиения (пункт 5 алгоритма)&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Основные шаги при реализации алгоритма&lt;br /&gt;
*	Генерация случайной матрицы размера &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на где &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;, проверка условий&lt;br /&gt;
*	Расчет центроидов – по сути, скалярное произведение с нормировкой&lt;br /&gt;
*	Расчет расстояний – в общепринятом случае является скалярным произведением&lt;br /&gt;
*	Пересчет матрицы – по сути, скалярное произведение&lt;br /&gt;
*	Проверка условий останова – вычисление нормы&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
    float ** FuzzyCMeans (float** X, c, m, eps){&lt;br /&gt;
        n = X.size();&lt;br /&gt;
        r = X[0].size();&lt;br /&gt;
        centers = generateZeroFill(c, r)&lt;br /&gt;
        Wprev = genetateRandFill(n, c);&lt;br /&gt;
        W = Wprev;&lt;br /&gt;
        while (true){&lt;br /&gt;
            // обновляем центры кластеров &lt;br /&gt;
            for (int i=0; i&amp;lt;c; i++){&lt;br /&gt;
                float * num = new float []();&lt;br /&gt;
                float den = 0;&lt;br /&gt;
                for (int j=0; j&amp;lt;n; j++){&lt;br /&gt;
                    num += pow(W[j][i], m) * X[j];&lt;br /&gt;
                    den+=pow(W[j][i], m);&lt;br /&gt;
                }&lt;br /&gt;
                centers[i] = num / den;&lt;br /&gt;
            }&lt;br /&gt;
            //обновляем вероятности W и считаем расстояние между матрицами W и Wprev&lt;br /&gt;
            float max_diff = 0;&lt;br /&gt;
            for (int i=0; i&amp;lt;n; i++)&lt;br /&gt;
                for (int j=0; j&amp;lt;c; j++){&lt;br /&gt;
                    total = 0;&lt;br /&gt;
                    for (int m=0; m&amp;lt;с; m++)&lt;br /&gt;
                        total += pow(distance(X[i], centers[j]) / distance(X[i], centers[m]), 2/(m-1));&lt;br /&gt;
                    W[i][j] = 1/total;&lt;br /&gt;
                    max_diff = max(abs(Wprev[i][j]-W[i][j]), max_diff);&lt;br /&gt;
                    Wprev[i][j] = W[i][j];&lt;br /&gt;
               }               &lt;br /&gt;
           if (max_diff &amp;lt; eps):                &lt;br /&gt;
                break;&lt;br /&gt;
        }&lt;br /&gt;
        return W;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Последовательная сложность алгоритма состоит из сложности каждой итерации умноженной на их количество. Так как число итераций заранее неизвестно и зависит от входных параметров, рассмотрим сложность на каждой итерации. Наибольшую сложность представляет собой пересчет матрицы, сложность которого &amp;lt;math&amp;gt;O(c^2 nd)&amp;lt;/math&amp;gt; (по сравнению со сложностью &amp;lt;math&amp;gt;O(cnd)&amp;lt;/math&amp;gt; расчета расстояний, вычисления центроидов и проверки условия останова). Итого общая сложность алгоритма &amp;lt;math&amp;gt;O(c^2 ndi)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
Информационный граф представлен на рисунке ниже.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 1, 2, совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз для каждого кластера. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 1&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 2&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m*X_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем вектор размера &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; и матрицу размера &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;. &lt;br /&gt;
Далее совершаем поэлементное сложение векторов и матриц соответственно, а затем делим каждый столбец в матрице на соответствующий элемент в векторе.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй ярус&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 3, 4, 5 также совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 3&#039;&#039;&#039;: обновление значения &amp;lt;math&amp;gt;w_{ij}&amp;lt;/math&amp;gt; по указанной в разделе 1.2 в пункте 5 формуле.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 4&#039;&#039;&#039;: &amp;lt;math&amp;gt;maximum = max(|w_{ij} - w_{ij}^{prev}|, maximum)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 5&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^{prev} = w_{ij}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем число &amp;lt;math&amp;gt;maximum&amp;lt;/math&amp;gt;. Далее находим максимальное значение из полученных величин для каждой ветки. Затем проверяем условие останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:Scheme3.JPG]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельная сложность алгоритма: &amp;lt;math&amp;gt;M*c^2*i&amp;lt;/math&amp;gt;. Такая сложность получается за счет распараллеливания на каждом ярусе &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; операций. Иерархическая структура параллелизма подробно описана в [[#Информационный граф|п.1.7]].&lt;br /&gt;
&lt;br /&gt;
В алгоритме не возникает скошенного параллелизма.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Входные данные алгоритма: набор векторов &amp;lt;math&amp;gt;x_i&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i = 1,...,M&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
* Объем входных данных: &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt; , [количество наблюдений * размерность].&lt;br /&gt;
* Выходные данные алгоритма: матрица вероятностей принадлежности векторов кластерам &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Объем выходных данных: &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt; , [количество наблюдений * количество кластеров].&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной формы алгоритма: &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;&lt;br /&gt;
* Вычислительная мощность: &amp;lt;math&amp;gt;{dc^2i} \over {c+d}&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Устойчивость: алгоритм не является устойчивым, поэтому существует много исследований о том, как первоначально выбрать параметры кластеризации.&lt;br /&gt;
* Сбалансированность: в данном алгоритме операция умножения доминирует над операцией сложения. Операции между параллельными ветвями сбалансированны.&lt;br /&gt;
* Детерминированность: алгоритм не является детерминированным, так как матрица нечеткого разбиение генерируется произвольно.&lt;br /&gt;
* Степень исхода вершины информационного графа ( для одной интерации): 2 (3 - с учетом, если выходные данные пошли на следующую итерацию).&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма = &lt;br /&gt;
&lt;br /&gt;
==Особенности реализации последовательного алгоритма==&lt;br /&gt;
&lt;br /&gt;
==Локальность данных и вычислений==&lt;br /&gt;
&lt;br /&gt;
==Возможные способы и особенности параллельной реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
Проведём исследование масштабируемости параллельной реализации нечеткого алгоритма С-средних. &lt;br /&gt;
Исследование проводилось на суперкомпьютере &amp;quot;Ломоносов&amp;quot;&amp;lt;ref name=&amp;quot;Lom&amp;quot;&amp;gt;Воеводин Вл., Жуматий С., Соболев С., Антонов А., Брызгалов П., Никитенко Д., Стефанов К., Воеводин Вад. Практика суперкомпьютера «Ломоносов» // Открытые системы, 2012, N 7, С. 36-39.&amp;lt;/ref&amp;gt; [http://parallel.ru/cluster Суперкомпьютерного комплекса Московского университета]. &lt;br /&gt;
Была исследована собственная параллельная реализация алгоритма, написанная на языке C++ с использованием стандарта MPI. Сборка программы производилась при помощи компилятора компании Intel версии 13.1.0 с использованием библиотеки intelMPI версии 4.1.0 . Расчеты проводились в разделе test на узлах со следующими характеристиками: количество GPU - 0, количество ядер - 8 ядер архитектуры x86, количество памяти - 12 Гб.&lt;br /&gt;
&lt;br /&gt;
Набор и границы значений изменяемых [[Глоссарий#Параметры запуска|параметров запуска]] реализации алгоритма: &lt;br /&gt;
&lt;br /&gt;
*	число процессоров [1 : 128];&lt;br /&gt;
*	размер матрицы [10000 : 80000].&lt;br /&gt;
&lt;br /&gt;
В результате проведённых экспериментов был получен следующий диапазон [[Глоссарий#Эффективность реализации|эффективности реализации]] алгоритма:&lt;br /&gt;
&lt;br /&gt;
*	минимальная эффективность реализации 0,33%;&lt;br /&gt;
*	максимальная эффективность реализации 9,4%.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
На следующих рисунках приведены графики [[Глоссарий#Производительность|производительности]] и  [[Глоссарий#Эффективность реализации|эффективности]] выбранной реализации в зависимости от изменяемых параметров запуска.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[file: FuzzyCMeansPerformance.png |thumb|center|700px|Рисунок 1. Параллельная реализация нечеткого алгоритма С-средних. Изменение производительности в зависимости от числа процессоров и размера матрицы.]]&lt;br /&gt;
[[file: FuzzyCMeansEfficiency2.png|thumb|center|700px|Рисунок 2. Параллельная реализация нечеткого алгоритма С-средних. Изменение эффективности реализации в зависимости от числа процессоров и размера матрицы.]]&lt;br /&gt;
&lt;br /&gt;
Построим оценки масштабируемости выбранной реализации нечеткого алгоритма С-средних:&lt;br /&gt;
*	По числу процессов: 0.007. При увеличении числа процессов эффективность на рассмотренной области изменений параметров запуска увеличивается.&lt;br /&gt;
*	По размеру задачи: -0.0016. При увеличении размера задачи эффективность уменьшается. &lt;br /&gt;
*	По двум направлениям: 0,000077. При рассмотрении увеличения как вычислительной сложности, так и числа процессов на всей рассмотренной области значений эффективность увеличивается, однако скорость увеличения эффективности небольшая.&lt;br /&gt;
&lt;br /&gt;
Была использована следующая реализация алгоритма. &lt;br /&gt;
&lt;br /&gt;
    #include &amp;lt;mpi.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;iostream&amp;gt;&lt;br /&gt;
    #include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;math.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;string.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;time.h&amp;gt;&lt;br /&gt;
    using namespace std;&lt;br /&gt;
    double **x; //input matrix of size (n x x_dim)&lt;br /&gt;
    int n;&lt;br /&gt;
    int x_dim;&lt;br /&gt;
    double **centroids; //cluster centroids matrix of size (n_cluster x x_dim)&lt;br /&gt;
    int n_cluster; // number of clusters&lt;br /&gt;
    double **w; //probability matrix of size (n x n_cluster)&lt;br /&gt;
    double **dist; //distances matrix of size (n x n_cluster)&lt;br /&gt;
    double eps; //max error&lt;br /&gt;
    double m; //parameter of algo&lt;br /&gt;
    int max_iter; // max num of iterations&lt;br /&gt;
    double **num;&lt;br /&gt;
    double *den;&lt;br /&gt;
    double *allden;&lt;br /&gt;
    double *err;&lt;br /&gt;
    double *total_err;&lt;br /&gt;
    int rank, size;&lt;br /&gt;
    double ** generateZerosMatrix(int r, int c){&lt;br /&gt;
        double ** arr = new double* [r];&lt;br /&gt;
        for (int i = 0; i &amp;lt; r; ++i){&lt;br /&gt;
            arr[i] = new double[c]();&lt;br /&gt;
        }&lt;br /&gt;
        return arr;&lt;br /&gt;
    }&lt;br /&gt;
    int generate_data()&lt;br /&gt;
    {&lt;br /&gt;
        //generate matrix&lt;br /&gt;
        x = generateZerosMatrix(n, x_dim);&lt;br /&gt;
        centroids = generateZerosMatrix(n_cluster, x_dim);&lt;br /&gt;
        w = generateZerosMatrix(n, n_cluster);&lt;br /&gt;
        dist = generateZerosMatrix(n, n_cluster);&lt;br /&gt;
        num = generateZerosMatrix(n_cluster, x_dim);&lt;br /&gt;
        //generate vectors&lt;br /&gt;
        den = new double [n_cluster]();&lt;br /&gt;
        allden = new double [n_cluster]();&lt;br /&gt;
        //for stopping algorithm&lt;br /&gt;
        err = new double;&lt;br /&gt;
        total_err = new double;&lt;br /&gt;
        srand(time(0));&lt;br /&gt;
        //initialize w randomly with restrictions&lt;br /&gt;
        for (int i = 0; i &amp;lt; n; ++i){&lt;br /&gt;
            double sum = 0;&lt;br /&gt;
            for (int j = 0; j &amp;lt; n_cluster; ++j){&lt;br /&gt;
                w[i][j] = rand();&lt;br /&gt;
                sum += w[i][j];&lt;br /&gt;
            }&lt;br /&gt;
            for (int j = 0; j &amp;lt; n_cluster; ++j){&lt;br /&gt;
                w[i][j] /= sum;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        //initialize x randomly&lt;br /&gt;
        for (int i = 0; i &amp;lt; n; ++i)&lt;br /&gt;
            for (int j = 0; j &amp;lt; x_dim; ++j)&lt;br /&gt;
                x[i][j] = rand();&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
    double make_iteration() {&lt;br /&gt;
        // calculate centroids centers&lt;br /&gt;
        for (int i = rank; i &amp;lt; n; i+=size)&lt;br /&gt;
            for (int j = 0; j &amp;lt; n_cluster; ++j){&lt;br /&gt;
                double mu = pow(w[i][j], m);&lt;br /&gt;
                den[j] += mu;&lt;br /&gt;
                for (int k = 0; k &amp;lt; x_dim; ++k)&lt;br /&gt;
                    num[j][k] = mu * x[i][k];&lt;br /&gt;
            }&lt;br /&gt;
        MPI_Allreduce(den, allden, n_cluster, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);&lt;br /&gt;
        for (int j=0; j &amp;lt; n_cluster; ++j)&lt;br /&gt;
            MPI_Allreduce(num[j], centroids[j], x_dim, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);&lt;br /&gt;
        for (int i = 0; i &amp;lt; n_cluster; ++i)&lt;br /&gt;
            for (int j = 0; j &amp;lt; x_dim; ++j)&lt;br /&gt;
                centroids[i][j] /= allden[i];&lt;br /&gt;
        // calculate distances and probabilities, check stop conditions&lt;br /&gt;
        double err = 0.0;&lt;br /&gt;
        for (int i = rank; i &amp;lt; n; i+=size)&lt;br /&gt;
            for (int j = 0; j &amp;lt; n_cluster; ++j){&lt;br /&gt;
                for (int k = 0; k &amp;lt; x_dim; ++k)&lt;br /&gt;
                    dist[i][j] += (x[i][k] - centroids[j][k]) * (x[i][k] - centroids[j][k]);&lt;br /&gt;
                double w_prev = w[i][j];&lt;br /&gt;
                for (int k = 0; k &amp;lt; n_cluster; ++k)&lt;br /&gt;
                    w[i][j] += dist[i][j] / dist[i][k];&lt;br /&gt;
                w[i][j] = 1.0 / pow(w[i][j], 1.0 / (m - 1));&lt;br /&gt;
                err = fmax(err, abs(w_prev - w[i][j]));&lt;br /&gt;
            }&lt;br /&gt;
        return err;&lt;br /&gt;
    }&lt;br /&gt;
    int FCM(){&lt;br /&gt;
        *total_err = eps+1;&lt;br /&gt;
        int cur_iter = 0;&lt;br /&gt;
        while (cur_iter &amp;lt; max_iter &amp;amp;&amp;amp; *total_err &amp;gt; eps){&lt;br /&gt;
            *err = make_iteration();&lt;br /&gt;
            MPI_Allreduce(err, total_err, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);&lt;br /&gt;
            cur_iter++;&lt;br /&gt;
        }&lt;br /&gt;
        return cur_iter;&lt;br /&gt;
    }&lt;br /&gt;
    void clearMatrix(double ** matr, int r, int c){&lt;br /&gt;
        for (int i = 0; i &amp;lt; r; ++i){&lt;br /&gt;
            delete [] matr[i];&lt;br /&gt;
        }&lt;br /&gt;
        delete [] matr;&lt;br /&gt;
    }&lt;br /&gt;
    int memory_free(){&lt;br /&gt;
        clearMatrix(x, n, x_dim);&lt;br /&gt;
        clearMatrix(centroids, n_cluster, x_dim);&lt;br /&gt;
        clearMatrix(w, n_cluster, n);&lt;br /&gt;
        clearMatrix(num, n_cluster, x_dim);&lt;br /&gt;
        clearMatrix(dist, n, n_cluster);&lt;br /&gt;
        delete [] den;&lt;br /&gt;
        delete [] allden;&lt;br /&gt;
        delete err;&lt;br /&gt;
        delete total_err;&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
    int main(int argc, char **argv){&lt;br /&gt;
        MPI_Init(&amp;amp;argc, &amp;amp;argv);&lt;br /&gt;
        MPI_Comm_size(MPI_COMM_WORLD, &amp;amp;size);&lt;br /&gt;
        MPI_Comm_rank(MPI_COMM_WORLD, &amp;amp;rank);&lt;br /&gt;
        int n_repeat = strtol(argv[1], NULL, 10);&lt;br /&gt;
        int nx_min = strtol(argv[2], NULL, 10);&lt;br /&gt;
        int nx_max = strtol(argv[3], NULL, 10);&lt;br /&gt;
        int step = strtol(argv[4], NULL, 10);&lt;br /&gt;
        x_dim = strtol(argv[5], NULL, 10);&lt;br /&gt;
        m = strtod(argv[6], NULL);&lt;br /&gt;
        n_cluster = strtol(argv[7], NULL, 10);&lt;br /&gt;
        max_iter = strtol(argv[8], NULL, 10);&lt;br /&gt;
        eps = strtod(argv[9], NULL);&lt;br /&gt;
        //for all input matrix sizes&lt;br /&gt;
        for (n = nx_min; n &amp;lt;= nx_max; n += step){&lt;br /&gt;
            double start, finish, time_elapsed_iter=0;&lt;br /&gt;
            int total_iterations = 0;&lt;br /&gt;
            //repeat for getting mean value&lt;br /&gt;
            for (int i = 0; i &amp;lt; n_repeat; ++i) {&lt;br /&gt;
                generate_data();&lt;br /&gt;
                MPI_Barrier(MPI_COMM_WORLD);&lt;br /&gt;
                start = MPI_Wtime();&lt;br /&gt;
                total_iterations += FCM();&lt;br /&gt;
                finish = MPI_Wtime();&lt;br /&gt;
                memory_free();&lt;br /&gt;
                time_elapsed_iter += (finish-start);&lt;br /&gt;
            }&lt;br /&gt;
            time_elapsed_iter /= total_iterations;&lt;br /&gt;
            if (rank == 0) {&lt;br /&gt;
                cout &amp;lt;&amp;lt; n &amp;lt;&amp;lt; &amp;quot; &amp;quot; &amp;lt;&amp;lt; size &amp;lt;&amp;lt; &amp;quot; &amp;quot; &amp;lt;&amp;lt; time_elapsed_iter &amp;lt;&amp;lt; endl;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        MPI_Finalize();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==Динамические характеристики и эффективность реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
==Выводы для классов архитектур==&lt;br /&gt;
&lt;br /&gt;
==Существующие реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
* Реализация алгоритма на POSTGRESQL: http://num-meth.srcc.msu.ru/zhurnal/tom_2012/pdf/v13r207.pdf&lt;br /&gt;
* Библиотека для MATLAB: http://www.mathworks.com/help/fuzzy/fcm.html (распространяется на коммерческой основе)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=21245</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=21245"/>
		<updated>2016-12-18T19:30:30Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|{{REVISIONUSER}}}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(Mdc^2i)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - количество итераций&lt;br /&gt;
| input_data         = &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt;, [количество наблюдений * размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt;, [количество наблюдений * количество кластеров]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;2i&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]] ([[#Вычислительное ядро алгоритма|1.3]]; [[#Схема реализации последовательного алгоритма|1.5]]; [[#Последовательная сложность алгоритма|1.6]]; [[#Информационный граф|1.7]]; [[#Масштабируемость алгоритма и его реализации|2.4]]; [[#Существующие реализации алгоритма|2.7]]), [[Участник:Yushin|Павел Юшин]] ([[#Общее описание алгоритма|1.1]]; [[#Математическое описание алгоритма|1.2]]; [[#Макроструктура алгоритма|1.4]]; [[#Ресурс параллелизма алгоритма|1.8]]; [[#Входные и выходные данные алгоритма|1.9]]; [[#Свойства алгоритма|1.10]])&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;[http://www.tandfonline.com/doi/abs/10.1080/01969727308546046 | J. C. Dunn. A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters. Journal of Cybernetics, volume 3,1973 - Issue 3, pp 32-57]&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов кластеризации, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров;&amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма не будут отличаться менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;[http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf | Нейский И.М. Классификация и сравнение методов кластеризации.// Интеллектуальные технологии и системы. Сборник учебно-методических работ и статей аспирантов и студентов. – М.: НОК «CLAIM», 2006. – Выпуск 8. – С. 130-142.]&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов, &amp;lt;math&amp;gt;X_i&amp;lt;/math&amp;gt; - набор входных векторов размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;i = 1,...,M&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M&amp;lt;/math&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;0 &amp;lt; \sum_{i = 1}^M w_{ij} &amp;lt; M, j = 1, ..., c&amp;lt;/math&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда алгоритм принимает следующий вид:&lt;br /&gt;
&lt;br /&gt;
1) Задаем параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
2) Генерируем случайным образом матрицу нечеткого разбиения с учетом условий &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3) Рассчитываем центроиды (центры кластеров): &amp;lt;math&amp;gt;V_j = {{\sum_{i=1}^M w_{ij}^m * X_i} \over {\sum_{i=1}^M w_{ij}^m}}, j = 1, ..., c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Рассчитываем расстояния между объектами &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и центроидами:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_{ij} = {||X_i - V_j||}, i = 1,...,M; j = 1,...,c &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5) Пересчет элементов матрицы разбиения:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} &amp;gt;0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = {{1}\over {{ (\sum_{k=1}^c {{D_{ij}}\over{D_{ik}}} ) }^{2/(m-1)}}}, j = 1,...,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} =0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = \delta_{ij}, j = 1,...,c&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\delta_{ij}&amp;lt;/math&amp;gt; - символ Кронекера&lt;br /&gt;
&lt;br /&gt;
6) Если &amp;lt;math&amp;gt;|| F - F^{*} || &amp;lt; \varepsilon &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;F^{*}&amp;lt;/math&amp;gt; - матрица нечеткого разбиения предыдущей итерации, то идем далее, иначе возвращаемся на пункт 3.&lt;br /&gt;
&lt;br /&gt;
7) Конец.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром алгоритма являются следующие пункты:&lt;br /&gt;
&lt;br /&gt;
* Поиск &amp;lt;math&amp;gt;V_j&amp;lt;/math&amp;gt; - расчет центроидов (пункт 3 алгоритма)&lt;br /&gt;
* Нахождение &amp;lt;math&amp;gt;D_{ij}&amp;lt;/math&amp;gt; - расстояний между объектами (пункт 4 алгоритма)&lt;br /&gt;
* Пересчет &amp;lt;math&amp;gt;w_{ij}&amp;lt;/math&amp;gt; - элементов матрицы разбиения (пункт 5 алгоритма)&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Основные шаги при реализации алгоритма&lt;br /&gt;
*	Генерация случайной матрицы размера &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на где &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;, проверка условий&lt;br /&gt;
*	Расчет центроидов – по сути, скалярное произведение с нормировкой&lt;br /&gt;
*	Расчет расстояний – в общепринятом случае является скалярным произведением&lt;br /&gt;
*	Пересчет матрицы – по сути, скалярное произведение&lt;br /&gt;
*	Проверка условий останова – вычисление нормы&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
    float ** FuzzyCMeans (float** X, c, m, eps){&lt;br /&gt;
        n = X.size();&lt;br /&gt;
        r = X[0].size();&lt;br /&gt;
        centers = generateZeroFill(c, r)&lt;br /&gt;
        Wprev = genetateRandFill(n, c);&lt;br /&gt;
        W = Wprev;&lt;br /&gt;
        while (true){&lt;br /&gt;
            // обновляем центры кластеров &lt;br /&gt;
            for (int i=0; i&amp;lt;c; i++){&lt;br /&gt;
                float * num = new float []();&lt;br /&gt;
                float den = 0;&lt;br /&gt;
                for (int j=0; j&amp;lt;n; j++){&lt;br /&gt;
                    num += pow(W[j][i], m) * X[j];&lt;br /&gt;
                    den+=pow(W[j][i], m);&lt;br /&gt;
                }&lt;br /&gt;
                centers[i] = num / den;&lt;br /&gt;
            }&lt;br /&gt;
            //обновляем вероятности W и считаем расстояние между матрицами W и Wprev&lt;br /&gt;
            float max_diff = 0;&lt;br /&gt;
            for (int i=0; i&amp;lt;n; i++)&lt;br /&gt;
                for (int j=0; j&amp;lt;c; j++){&lt;br /&gt;
                    total = 0;&lt;br /&gt;
                    for (int m=0; m&amp;lt;с; m++)&lt;br /&gt;
                        total += pow(distance(X[i], centers[j]) / distance(X[i], centers[m]), 2/(m-1));&lt;br /&gt;
                    W[i][j] = 1/total;&lt;br /&gt;
                    max_diff = max(abs(Wprev[i][j]-W[i][j]), max_diff);&lt;br /&gt;
                    Wprev[i][j] = W[i][j];&lt;br /&gt;
               }               &lt;br /&gt;
           if (max_diff &amp;lt; eps):                &lt;br /&gt;
                break;&lt;br /&gt;
        }&lt;br /&gt;
        return W;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Последовательная сложность алгоритма состоит из сложности каждой итерации умноженной на их количество. Так как число итераций заранее неизвестно и зависит от входных параметров, рассмотрим сложность на каждой итерации. Наибольшую сложность представляет собой пересчет матрицы, сложность которого &amp;lt;math&amp;gt;O(c^2 nd)&amp;lt;/math&amp;gt; (по сравнению со сложностью &amp;lt;math&amp;gt;O(cnd)&amp;lt;/math&amp;gt; расчета расстояний, вычисления центроидов и проверки условия останова). Итого общая сложность алгоритма &amp;lt;math&amp;gt;O(c^2 ndi)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
Информационный граф представлен на рисунке ниже.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 1, 2, совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз для каждого кластера. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 1&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 2&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m*X_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем вектор размера &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; и матрицу размера &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;. &lt;br /&gt;
Далее совершаем поэлементное сложение векторов и матриц соответственно, а затем делим каждый столбец в матрице на соответствующий элемент в векторе.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй ярус&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 3, 4, 5 также совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 3&#039;&#039;&#039;: обновление значения &amp;lt;math&amp;gt;w_{ij}&amp;lt;/math&amp;gt; по указанной в разделе 1.2 в пункте 5 формуле.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 4&#039;&#039;&#039;: &amp;lt;math&amp;gt;maximum = max(|w_{ij} - w_{ij}^{prev}|, maximum)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 5&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^{prev} = w_{ij}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем число &amp;lt;math&amp;gt;maximum&amp;lt;/math&amp;gt;. Далее находим максимальное значение из полученных величин для каждой ветки. Затем проверяем условие останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:Scheme3.JPG]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельная сложность алгоритма: &amp;lt;math&amp;gt;M*c^2*i&amp;lt;/math&amp;gt;. Такая сложность получается за счет распараллеливания на каждом ярусе &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; операций. Иерархическая структура параллелизма подробно описана в [[#Информационный граф|п.1.7]].&lt;br /&gt;
&lt;br /&gt;
В алгоритме не возникает скошенного параллелизма.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Входные данные алгоритма: набор векторов &amp;lt;math&amp;gt;x_i&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i = 1,...,M&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
* Объем входных данных: &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt; , [количество наблюдений * размерность].&lt;br /&gt;
* Выходные данные алгоритма: матрица вероятностей принадлежности векторов кластерам &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Объем выходных данных: &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt; , [количество наблюдений * количество кластеров].&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной формы алгоритма: &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;&lt;br /&gt;
* Вычислительная мощность: &amp;lt;math&amp;gt;{dc^2i} \over {c+d}&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Устойчивость: алгоритм не является устойчивым, поэтому существует много исследований о том, как первоначально выбрать параметры кластеризации.&lt;br /&gt;
* Сбалансированность: в данном алгоритме операция умножения доминирует над операцией сложения. Операции между параллельными ветвями сбалансированны.&lt;br /&gt;
* Детерминированность: алгоритм не является детерминированным, так как матрица нечеткого разбиение генерируется произвольно.&lt;br /&gt;
* Степень исхода вершины информационного графа ( для одной интерации): 2 (3 - с учетом, если выходные данные пошли на следующую итерацию).&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма = &lt;br /&gt;
&lt;br /&gt;
==Особенности реализации последовательного алгоритма==&lt;br /&gt;
&lt;br /&gt;
==Локальность данных и вычислений==&lt;br /&gt;
&lt;br /&gt;
==Возможные способы и особенности параллельной реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
Проведём исследование масштабируемости параллельной реализации нечеткого алгоритма С-средних. &lt;br /&gt;
Исследование проводилось на суперкомпьютере &amp;quot;Ломоносов&amp;quot;&amp;lt;ref name=&amp;quot;Lom&amp;quot;&amp;gt;Воеводин Вл., Жуматий С., Соболев С., Антонов А., Брызгалов П., Никитенко Д., Стефанов К., Воеводин Вад. Практика суперкомпьютера «Ломоносов» // Открытые системы, 2012, N 7, С. 36-39.&amp;lt;/ref&amp;gt; [http://parallel.ru/cluster Суперкомпьютерного комплекса Московского университета]. &lt;br /&gt;
Была исследована собственная параллельная реализация алгоритма, написанная на языке C++ с использованием стандарта MPI. Сборка программы производилась при помощи компилятора компании Intel версии 13.1.0 с использованием библиотеки intelMPI версии 4.1.0 . Расчеты проводились в разделе test на узлах со следующими характеристиками: количество GPU - 0, количество ядер - 8 ядер архитектуры x86, количество памяти - 12 Гб.&lt;br /&gt;
&lt;br /&gt;
Набор и границы значений изменяемых [[Глоссарий#Параметры запуска|параметров запуска]] реализации алгоритма: &lt;br /&gt;
&lt;br /&gt;
*	число процессоров [1 : 128];&lt;br /&gt;
*	размер матрицы [10000 : 80000].&lt;br /&gt;
&lt;br /&gt;
В результате проведённых экспериментов был получен следующий диапазон [[Глоссарий#Эффективность реализации|эффективности реализации]] алгоритма:&lt;br /&gt;
&lt;br /&gt;
*	минимальная эффективность реализации 0,33%;&lt;br /&gt;
*	максимальная эффективность реализации 9,4%.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
На следующих рисунках приведены графики [[Глоссарий#Производительность|производительности]] и  [[Глоссарий#Эффективность реализации|эффективности]] выбранной реализации в зависимости от изменяемых параметров запуска.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[file: FuzzyCMeansPerformance.png |thumb|center|700px|Рисунок 1. Параллельная реализация нечеткого алгоритма С-средних. Изменение производительности в зависимости от числа процессоров и размера матрицы.]]&lt;br /&gt;
[[file: FuzzyCMeansEfficiency2.png|thumb|center|700px|Рисунок 2. Параллельная реализация нечеткого алгоритма С-средних. Изменение эффективности реализации в зависимости от числа процессоров и размера матрицы.]]&lt;br /&gt;
&lt;br /&gt;
Построим оценки масштабируемости выбранной реализации нечеткого алгоритма С-средних:&lt;br /&gt;
*	По числу процессов: 0.007. При увеличении числа процессов эффективность на рассмотренной области изменений параметров запуска увеличивается.&lt;br /&gt;
*	По размеру задачи: -0.0016. При увеличении размера задачи эффективность уменьшается. &lt;br /&gt;
*	По двум направлениям: 0,000077. При рассмотрении увеличения как вычислительной сложности, так и числа процессов на всей рассмотренной области значений эффективность увеличивается, однако скорость увеличения эффективности небольшая.&lt;br /&gt;
&lt;br /&gt;
Была использована следующая реализация алгоритма. &lt;br /&gt;
&lt;br /&gt;
    #include &amp;lt;mpi.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;iostream&amp;gt;&lt;br /&gt;
    #include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;math.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;string.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;time.h&amp;gt;&lt;br /&gt;
    using namespace std;&lt;br /&gt;
    double **x; //input matrix of size (n x x_dim)&lt;br /&gt;
    int n;&lt;br /&gt;
    int x_dim;&lt;br /&gt;
    double **centroids; //cluster centroids matrix of size (n_cluster x x_dim)&lt;br /&gt;
    int n_cluster; // number of clusters&lt;br /&gt;
    double **w; //probability matrix of size (n x n_cluster)&lt;br /&gt;
    double **dist; //distances matrix of size (n x n_cluster)&lt;br /&gt;
    double eps; //max error&lt;br /&gt;
    double m; //parameter of algo&lt;br /&gt;
    int max_iter; // max num of iterations&lt;br /&gt;
    double **num;&lt;br /&gt;
    double *den;&lt;br /&gt;
    double *allden;&lt;br /&gt;
    double *err;&lt;br /&gt;
    double *total_err;&lt;br /&gt;
    int rank, size;&lt;br /&gt;
    double ** generateZerosMatrix(int r, int c){&lt;br /&gt;
        double ** arr = new double* [r];&lt;br /&gt;
        for (int i = 0; i &amp;lt; r; ++i){&lt;br /&gt;
            arr[i] = new double[c]();&lt;br /&gt;
        }&lt;br /&gt;
        return arr;&lt;br /&gt;
    }&lt;br /&gt;
    int generate_data()&lt;br /&gt;
    {&lt;br /&gt;
        //generate matrix&lt;br /&gt;
        x = generateZerosMatrix(n, x_dim);&lt;br /&gt;
        centroids = generateZerosMatrix(n_cluster, x_dim);&lt;br /&gt;
        w = generateZerosMatrix(n, n_cluster);&lt;br /&gt;
        dist = generateZerosMatrix(n, n_cluster);&lt;br /&gt;
        num = generateZerosMatrix(n_cluster, x_dim);&lt;br /&gt;
        //generate vectors&lt;br /&gt;
        den = new double [n_cluster]();&lt;br /&gt;
        allden = new double [n_cluster]();&lt;br /&gt;
        //for stopping algorithm&lt;br /&gt;
        err = new double;&lt;br /&gt;
        total_err = new double;&lt;br /&gt;
        srand(time(0));&lt;br /&gt;
        //initialize w randomly with restrictions&lt;br /&gt;
        for (int i = 0; i &amp;lt; n; ++i){&lt;br /&gt;
            double sum = 0;&lt;br /&gt;
            for (int j = 0; j &amp;lt; n_cluster; ++j){&lt;br /&gt;
                w[i][j] = rand();&lt;br /&gt;
                sum += w[i][j];&lt;br /&gt;
            }&lt;br /&gt;
            for (int j = 0; j &amp;lt; n_cluster; ++j){&lt;br /&gt;
                w[i][j] /= sum;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        //initialize x randomly&lt;br /&gt;
        for (int i = 0; i &amp;lt; n; ++i)&lt;br /&gt;
            for (int j = 0; j &amp;lt; x_dim; ++j)&lt;br /&gt;
                x[i][j] = rand();&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
    double make_iteration() {&lt;br /&gt;
        // calculate centroids centers&lt;br /&gt;
        for (int i = rank; i &amp;lt; n; i+=size)&lt;br /&gt;
            for (int j = 0; j &amp;lt; n_cluster; ++j){&lt;br /&gt;
                double mu = pow(w[i][j], m);&lt;br /&gt;
                den[j] += mu;&lt;br /&gt;
                for (int k = 0; k &amp;lt; x_dim; ++k)&lt;br /&gt;
                    num[j][k] = mu * x[i][k];&lt;br /&gt;
            }&lt;br /&gt;
        MPI_Allreduce(den, allden, n_cluster, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);&lt;br /&gt;
        for (int j=0; j &amp;lt; n_cluster; ++j)&lt;br /&gt;
            MPI_Allreduce(num[j], centroids[j], x_dim, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);&lt;br /&gt;
        for (int i = 0; i &amp;lt; n_cluster; ++i)&lt;br /&gt;
            for (int j = 0; j &amp;lt; x_dim; ++j)&lt;br /&gt;
                centroids[i][j] /= allden[i];&lt;br /&gt;
        // calculate distances and probabilities, check stop conditions&lt;br /&gt;
        double err = 0.0;&lt;br /&gt;
        for (int i = rank; i &amp;lt; n; i+=size)&lt;br /&gt;
            for (int j = 0; j &amp;lt; n_cluster; ++j){&lt;br /&gt;
                for (int k = 0; k &amp;lt; x_dim; ++k)&lt;br /&gt;
                    dist[i][j] += (x[i][k] - centroids[j][k]) * (x[i][k] - centroids[j][k]);&lt;br /&gt;
                double w_prev = w[i][j];&lt;br /&gt;
                for (int k = 0; k &amp;lt; n_cluster; ++k)&lt;br /&gt;
                    w[i][j] += dist[i][j] / dist[i][k];&lt;br /&gt;
                w[i][j] = 1.0 / pow(w[i][j], 1.0 / (m - 1));&lt;br /&gt;
                err = fmax(err, abs(w_prev - w[i][j]));&lt;br /&gt;
            }&lt;br /&gt;
        return err;&lt;br /&gt;
    }&lt;br /&gt;
    int FCM(){&lt;br /&gt;
        *total_err = eps+1;&lt;br /&gt;
        int cur_iter = 0;&lt;br /&gt;
        while (cur_iter &amp;lt; max_iter &amp;amp;&amp;amp; *total_err &amp;gt; eps){&lt;br /&gt;
            *err = make_iteration();&lt;br /&gt;
            MPI_Allreduce(err, total_err, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);&lt;br /&gt;
            cur_iter++;&lt;br /&gt;
        }&lt;br /&gt;
        return cur_iter;&lt;br /&gt;
    }&lt;br /&gt;
    void clearMatrix(double ** matr, int r, int c){&lt;br /&gt;
        for (int i = 0; i &amp;lt; r; ++i){&lt;br /&gt;
            delete [] matr[i];&lt;br /&gt;
        }&lt;br /&gt;
        delete [] matr;&lt;br /&gt;
    }&lt;br /&gt;
    int memory_free(){&lt;br /&gt;
        clearMatrix(x, n, x_dim);&lt;br /&gt;
        clearMatrix(centroids, n_cluster, x_dim);&lt;br /&gt;
        clearMatrix(w, n_cluster, n);&lt;br /&gt;
        clearMatrix(num, n_cluster, x_dim);&lt;br /&gt;
        clearMatrix(dist, n, n_cluster);&lt;br /&gt;
        delete [] den;&lt;br /&gt;
        delete [] allden;&lt;br /&gt;
        delete err;&lt;br /&gt;
        delete total_err;&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
    int main(int argc, char **argv){&lt;br /&gt;
        MPI_Init(&amp;amp;argc, &amp;amp;argv);&lt;br /&gt;
        MPI_Comm_size(MPI_COMM_WORLD, &amp;amp;size);&lt;br /&gt;
        MPI_Comm_rank(MPI_COMM_WORLD, &amp;amp;rank);&lt;br /&gt;
        int n_repeat = strtol(argv[1], NULL, 10);&lt;br /&gt;
        int nx_min = strtol(argv[2], NULL, 10);&lt;br /&gt;
        int nx_max = strtol(argv[3], NULL, 10);&lt;br /&gt;
        int step = strtol(argv[4], NULL, 10);&lt;br /&gt;
        x_dim = strtol(argv[5], NULL, 10);&lt;br /&gt;
        m = strtod(argv[6], NULL);&lt;br /&gt;
        n_cluster = strtol(argv[7], NULL, 10);&lt;br /&gt;
        max_iter = strtol(argv[8], NULL, 10);&lt;br /&gt;
        eps = strtod(argv[9], NULL);&lt;br /&gt;
        //for all input matrix sizes&lt;br /&gt;
        for (n = nx_min; n &amp;lt;= nx_max; n += step){&lt;br /&gt;
            double start, finish, time_elapsed_iter=0;&lt;br /&gt;
            int total_iterations = 0;&lt;br /&gt;
            //repeat for getting mean value&lt;br /&gt;
            for (int i = 0; i &amp;lt; n_repeat; ++i) {&lt;br /&gt;
                generate_data();&lt;br /&gt;
                MPI_Barrier(MPI_COMM_WORLD);&lt;br /&gt;
                start = MPI_Wtime();&lt;br /&gt;
                total_iterations += FCM();&lt;br /&gt;
                finish = MPI_Wtime();&lt;br /&gt;
                memory_free();&lt;br /&gt;
                time_elapsed_iter += (finish-start);&lt;br /&gt;
            }&lt;br /&gt;
            time_elapsed_iter /= total_iterations;&lt;br /&gt;
            if (rank == 0) {&lt;br /&gt;
                cout &amp;lt;&amp;lt; n &amp;lt;&amp;lt; &amp;quot; &amp;quot; &amp;lt;&amp;lt; size &amp;lt;&amp;lt; &amp;quot; &amp;quot; &amp;lt;&amp;lt; time_elapsed_iter &amp;lt;&amp;lt; endl;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        MPI_Finalize();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==Динамические характеристики и эффективность реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
==Выводы для классов архитектур==&lt;br /&gt;
&lt;br /&gt;
==Существующие реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
* Реализация алгоритма на POSTGRESQL: http://num-meth.srcc.msu.ru/zhurnal/tom_2012/pdf/v13r207.pdf&lt;br /&gt;
* Библиотека для MATLAB: http://www.mathworks.com/help/fuzzy/fcm.html (распространяется на коммерческой основе)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=21244</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=21244"/>
		<updated>2016-12-18T19:22:01Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|{{REVISIONUSER}}}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(Mdc^2i)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - количество итераций&lt;br /&gt;
| input_data         = &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt;, [количество наблюдений * размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt;, [количество наблюдений * количество кластеров]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;2i&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]] ([[#Вычислительное ядро алгоритма|1.3]]; [[#Схема реализации последовательного алгоритма|1.5]]; [[#Последовательная сложность алгоритма|1.6]]; [[#Информационный граф|1.7]]; [[#Масштабируемость алгоритма и его реализации|2.4]]; [[#Существующие реализации алгоритма|2.7]]), [[Участник:Yushin|Павел Юшин]] ([[#Общее описание алгоритма|1.1]]; [[#Математическое описание алгоритма|1.2]]; [[#Макроструктура алгоритма|1.4]]; [[#Ресурс параллелизма алгоритма|1.8]]; [[#Входные и выходные данные алгоритма|1.9]]; [[#Свойства алгоритма|1.10]])&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;[http://www.tandfonline.com/doi/abs/10.1080/01969727308546046 | J. C. Dunn. A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters. Journal of Cybernetics, volume 3,1973 - Issue 3, pp 32-57]&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов кластеризации, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров;&amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма не будут отличаться менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;[http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf | Нейский И.М. Классификация и сравнение методов кластеризации.// Интеллектуальные технологии и системы. Сборник учебно-методических работ и статей аспирантов и студентов. – М.: НОК «CLAIM», 2006. – Выпуск 8. – С. 130-142.]&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M&amp;lt;/math&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;0 &amp;lt; \sum_{i = 1}^M w_{ij} &amp;lt; M, j = 1, ..., c&amp;lt;/math&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда алгоритм принимает следующий вид:&lt;br /&gt;
&lt;br /&gt;
1) Задаем параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
2) Генерируем случайным образом матрицу нечеткого разбиения с учетом условий &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3) Рассчитываем центроиды (центры кластеров): &amp;lt;math&amp;gt;V_j = {{\sum_{i=1}^M w_{ij}^m * X_i} \over {\sum_{i=1}^M w_{ij}^m}}, j = 1, ..., c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Рассчитываем расстояния между объектами &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и центроидами:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_{ij} = {||X_i - V_j||}, i = 1,...,M; j = 1,...,c &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5) Пересчет элементов матрицы разбиения:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} &amp;gt;0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = {{1}\over {{ (\sum_{k=1}^c {{D_{ij}}\over{D_{ik}}} ) }^{2/(m-1)}}}, j = 1,...,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} =0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = \delta_{ij}, j = 1,...,c&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\delta_{ij}&amp;lt;/math&amp;gt; - символ Кронекера&lt;br /&gt;
&lt;br /&gt;
6) Если &amp;lt;math&amp;gt;|| F - F^{*} || &amp;lt; \varepsilon &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;F^{*}&amp;lt;/math&amp;gt; - матрица нечеткого разбиения предыдущей итерации, то идем далее, иначе возвращаемся на пункт 3.&lt;br /&gt;
&lt;br /&gt;
7) Конец.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром алгоритма являются следующие пункты:&lt;br /&gt;
&lt;br /&gt;
* Поиск &amp;lt;math&amp;gt;V_j&amp;lt;/math&amp;gt; - расчет центроидов (пункт 3 алгоритма)&lt;br /&gt;
* Нахождение &amp;lt;math&amp;gt;D_{ij}&amp;lt;/math&amp;gt; - расстояний между объектами (пункт 4 алгоритма)&lt;br /&gt;
* Пересчет &amp;lt;math&amp;gt;w_{ij}&amp;lt;/math&amp;gt; - элементов матрицы разбиения (пункт 5 алгоритма)&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Основные шаги при реализации алгоритма&lt;br /&gt;
*	Генерация случайной матрицы размера &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на где &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;, проверка условий&lt;br /&gt;
*	Расчет центроидов – по сути, скалярное произведение с нормировкой&lt;br /&gt;
*	Расчет расстояний – в общепринятом случае является скалярным произведением&lt;br /&gt;
*	Пересчет матрицы – по сути, скалярное произведение&lt;br /&gt;
*	Проверка условий останова – вычисление нормы&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
    float ** FuzzyCMeans (float** X, c, m, eps){&lt;br /&gt;
        n = X.size();&lt;br /&gt;
        r = X[0].size();&lt;br /&gt;
        centers = generateZeroFill(c, r)&lt;br /&gt;
        Wprev = genetateRandFill(n, c);&lt;br /&gt;
        W = Wprev;&lt;br /&gt;
        while (true){&lt;br /&gt;
            // обновляем центры кластеров &lt;br /&gt;
            for (int i=0; i&amp;lt;c; i++){&lt;br /&gt;
                float * num = new float []();&lt;br /&gt;
                float den = 0;&lt;br /&gt;
                for (int j=0; j&amp;lt;n; j++){&lt;br /&gt;
                    num += pow(W[j][i], m) * X[j];&lt;br /&gt;
                    den+=pow(W[j][i], m);&lt;br /&gt;
                }&lt;br /&gt;
                centers[i] = num / den;&lt;br /&gt;
            }&lt;br /&gt;
            //обновляем вероятности W и считаем расстояние между матрицами W и Wprev&lt;br /&gt;
            float max_diff = 0;&lt;br /&gt;
            for (int i=0; i&amp;lt;n; i++)&lt;br /&gt;
                for (int j=0; j&amp;lt;c; j++){&lt;br /&gt;
                    total = 0;&lt;br /&gt;
                    for (int m=0; m&amp;lt;с; m++)&lt;br /&gt;
                        total += pow(distance(X[i], centers[j]) / distance(X[i], centers[m]), 2/(m-1));&lt;br /&gt;
                    W[i][j] = 1/total;&lt;br /&gt;
                    max_diff = max(abs(Wprev[i][j]-W[i][j]), max_diff);&lt;br /&gt;
                    Wprev[i][j] = W[i][j];&lt;br /&gt;
               }               &lt;br /&gt;
           if (max_diff &amp;lt; eps):                &lt;br /&gt;
                break;&lt;br /&gt;
        }&lt;br /&gt;
        return W;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Последовательная сложность алгоритма состоит из сложности каждой итерации умноженной на их количество. Так как число итераций заранее неизвестно и зависит от входных параметров, рассмотрим сложность на каждой итерации. Наибольшую сложность представляет собой пересчет матрицы, сложность которого &amp;lt;math&amp;gt;O(c^2 nd)&amp;lt;/math&amp;gt; (по сравнению со сложностью &amp;lt;math&amp;gt;O(cnd)&amp;lt;/math&amp;gt; расчета расстояний, вычисления центроидов и проверки условия останова). Итого общая сложность алгоритма &amp;lt;math&amp;gt;O(c^2 ndi)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
Информационный граф представлен на рисунке ниже.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 1, 2, совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз для каждого кластера. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 1&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 2&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m*X_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем вектор размера &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; и матрицу размера &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;. &lt;br /&gt;
Далее совершаем поэлементное сложение векторов и матриц соответственно, а затем делим каждый столбец в матрице на соответствующий элемент в векторе.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй ярус&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 3, 4, 5 также совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 3&#039;&#039;&#039;: обновление значения &amp;lt;math&amp;gt;w_{ij}&amp;lt;/math&amp;gt; по указанной в разделе 1.2 в пункте 5 формуле.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 4&#039;&#039;&#039;: &amp;lt;math&amp;gt;maximum = max(|w_{ij} - w_{ij}^{prev}|, maximum)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 5&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^{prev} = w_{ij}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем число &amp;lt;math&amp;gt;maximum&amp;lt;/math&amp;gt;. Далее находим максимальное значение из полученных величин для каждой ветки. Затем проверяем условие останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:Scheme3.JPG]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельная сложность алгоритма: &amp;lt;math&amp;gt;M*c^2*i&amp;lt;/math&amp;gt;. Такая сложность получается за счет распараллеливания на каждом ярусе &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; операций. Иерархическая структура параллелизма подробно описана в [[#Информационный граф|п.1.7]].&lt;br /&gt;
&lt;br /&gt;
В алгоритме не возникает скошенного параллелизма.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Входные данные алгоритма: набор векторов &amp;lt;math&amp;gt;x_i&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i = 1,...,M&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
* Объем входных данных: &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt; , [количество наблюдений * размерность].&lt;br /&gt;
* Выходные данные алгоритма: матрица вероятностей принадлежности векторов кластерам &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Объем выходных данных: &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt; , [количество наблюдений * количество кластеров].&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной формы алгоритма: &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;&lt;br /&gt;
* Вычислительная мощность: &amp;lt;math&amp;gt;{dc^2i} \over {c+d}&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Устойчивость: алгоритм не является устойчивым, поэтому существует много исследований о том, как первоначально выбрать параметры кластеризации.&lt;br /&gt;
* Сбалансированность: в данном алгоритме операция умножения доминирует над операцией сложения. Операции между параллельными ветвями сбалансированны.&lt;br /&gt;
* Детерминированность: алгоритм не является детерминированным, так как матрица нечеткого разбиение генерируется произвольно.&lt;br /&gt;
* Степень исхода вершины информационного графа ( для одной интерации): 2 (3 - с учетом, если выходные данные пошли на следующую итерацию).&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма = &lt;br /&gt;
&lt;br /&gt;
==Особенности реализации последовательного алгоритма==&lt;br /&gt;
&lt;br /&gt;
==Локальность данных и вычислений==&lt;br /&gt;
&lt;br /&gt;
==Возможные способы и особенности параллельной реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
Проведём исследование масштабируемости параллельной реализации нечеткого алгоритма С-средних. &lt;br /&gt;
Исследование проводилось на суперкомпьютере &amp;quot;Ломоносов&amp;quot;&amp;lt;ref name=&amp;quot;Lom&amp;quot;&amp;gt;Воеводин Вл., Жуматий С., Соболев С., Антонов А., Брызгалов П., Никитенко Д., Стефанов К., Воеводин Вад. Практика суперкомпьютера «Ломоносов» // Открытые системы, 2012, N 7, С. 36-39.&amp;lt;/ref&amp;gt; [http://parallel.ru/cluster Суперкомпьютерного комплекса Московского университета]. &lt;br /&gt;
Была исследована собственная параллельная реализация алгоритма, написанная на языке C++ с использованием стандарта MPI. Сборка программы производилась при помощи компилятора компании Intel версии 13.1.0 с использованием библиотеки intelMPI версии 4.1.0 . Расчеты проводились в разделе test на узлах со следующими характеристиками: количество GPU - 0, количество ядер - 8 ядер архитектуры x86, количество памяти - 12 Гб.&lt;br /&gt;
&lt;br /&gt;
Набор и границы значений изменяемых [[Глоссарий#Параметры запуска|параметров запуска]] реализации алгоритма: &lt;br /&gt;
&lt;br /&gt;
*	число процессоров [1 : 128];&lt;br /&gt;
*	размер матрицы [10000 : 80000].&lt;br /&gt;
&lt;br /&gt;
В результате проведённых экспериментов был получен следующий диапазон [[Глоссарий#Эффективность реализации|эффективности реализации]] алгоритма:&lt;br /&gt;
&lt;br /&gt;
*	минимальная эффективность реализации 0,33%;&lt;br /&gt;
*	максимальная эффективность реализации 9,4%.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
На следующих рисунках приведены графики [[Глоссарий#Производительность|производительности]] и  [[Глоссарий#Эффективность реализации|эффективности]] выбранной реализации в зависимости от изменяемых параметров запуска.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[file: FuzzyCMeansPerformance.png |thumb|center|700px|Рисунок 1. Параллельная реализация нечеткого алгоритма С-средних. Изменение производительности в зависимости от числа процессоров и размера матрицы.]]&lt;br /&gt;
[[file: FuzzyCMeansEfficiency2.png|thumb|center|700px|Рисунок 2. Параллельная реализация нечеткого алгоритма С-средних. Изменение эффективности реализации в зависимости от числа процессоров и размера матрицы.]]&lt;br /&gt;
&lt;br /&gt;
Построим оценки масштабируемости выбранной реализации нечеткого алгоритма С-средних:&lt;br /&gt;
*	По числу процессов: 0.007. При увеличении числа процессов эффективность на рассмотренной области изменений параметров запуска увеличивается.&lt;br /&gt;
*	По размеру задачи: -0.0016. При увеличении размера задачи эффективность уменьшается. &lt;br /&gt;
*	По двум направлениям: 0,000077. При рассмотрении увеличения как вычислительной сложности, так и числа процессов на всей рассмотренной области значений эффективность увеличивается, однако скорость увеличения эффективности небольшая.&lt;br /&gt;
&lt;br /&gt;
Была использована следующая реализация алгоритма. &lt;br /&gt;
&lt;br /&gt;
    #include &amp;lt;mpi.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;iostream&amp;gt;&lt;br /&gt;
    #include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;math.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;string.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;time.h&amp;gt;&lt;br /&gt;
    using namespace std;&lt;br /&gt;
    double **x; //input matrix of size (n x x_dim)&lt;br /&gt;
    int n;&lt;br /&gt;
    int x_dim;&lt;br /&gt;
    double **centroids; //cluster centroids matrix of size (n_cluster x x_dim)&lt;br /&gt;
    int n_cluster; // number of clusters&lt;br /&gt;
    double **w; //probability matrix of size (n x n_cluster)&lt;br /&gt;
    double **dist; //distances matrix of size (n x n_cluster)&lt;br /&gt;
    double eps; //max error&lt;br /&gt;
    double m; //parameter of algo&lt;br /&gt;
    int max_iter; // max num of iterations&lt;br /&gt;
    double **num;&lt;br /&gt;
    double *den;&lt;br /&gt;
    double *allden;&lt;br /&gt;
    double *err;&lt;br /&gt;
    double *total_err;&lt;br /&gt;
    int rank, size;&lt;br /&gt;
    double ** generateZerosMatrix(int r, int c){&lt;br /&gt;
        double ** arr = new double* [r];&lt;br /&gt;
        for (int i = 0; i &amp;lt; r; ++i){&lt;br /&gt;
            arr[i] = new double[c]();&lt;br /&gt;
        }&lt;br /&gt;
        return arr;&lt;br /&gt;
    }&lt;br /&gt;
    int generate_data()&lt;br /&gt;
    {&lt;br /&gt;
        //generate matrix&lt;br /&gt;
        x = generateZerosMatrix(n, x_dim);&lt;br /&gt;
        centroids = generateZerosMatrix(n_cluster, x_dim);&lt;br /&gt;
        w = generateZerosMatrix(n, n_cluster);&lt;br /&gt;
        dist = generateZerosMatrix(n, n_cluster);&lt;br /&gt;
        num = generateZerosMatrix(n_cluster, x_dim);&lt;br /&gt;
        //generate vectors&lt;br /&gt;
        den = new double [n_cluster]();&lt;br /&gt;
        allden = new double [n_cluster]();&lt;br /&gt;
        //for stopping algorithm&lt;br /&gt;
        err = new double;&lt;br /&gt;
        total_err = new double;&lt;br /&gt;
        srand(time(0));&lt;br /&gt;
        //initialize w randomly with restrictions&lt;br /&gt;
        for (int i = 0; i &amp;lt; n; ++i){&lt;br /&gt;
            double sum = 0;&lt;br /&gt;
            for (int j = 0; j &amp;lt; n_cluster; ++j){&lt;br /&gt;
                w[i][j] = rand();&lt;br /&gt;
                sum += w[i][j];&lt;br /&gt;
            }&lt;br /&gt;
            for (int j = 0; j &amp;lt; n_cluster; ++j){&lt;br /&gt;
                w[i][j] /= sum;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        //initialize x randomly&lt;br /&gt;
        for (int i = 0; i &amp;lt; n; ++i)&lt;br /&gt;
            for (int j = 0; j &amp;lt; x_dim; ++j)&lt;br /&gt;
                x[i][j] = rand();&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
    double make_iteration() {&lt;br /&gt;
        // calculate centroids centers&lt;br /&gt;
        for (int i = rank; i &amp;lt; n; i+=size)&lt;br /&gt;
            for (int j = 0; j &amp;lt; n_cluster; ++j){&lt;br /&gt;
                double mu = pow(w[i][j], m);&lt;br /&gt;
                den[j] += mu;&lt;br /&gt;
                for (int k = 0; k &amp;lt; x_dim; ++k)&lt;br /&gt;
                    num[j][k] = mu * x[i][k];&lt;br /&gt;
            }&lt;br /&gt;
        MPI_Allreduce(den, allden, n_cluster, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);&lt;br /&gt;
        for (int j=0; j &amp;lt; n_cluster; ++j)&lt;br /&gt;
            MPI_Allreduce(num[j], centroids[j], x_dim, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);&lt;br /&gt;
        for (int i = 0; i &amp;lt; n_cluster; ++i)&lt;br /&gt;
            for (int j = 0; j &amp;lt; x_dim; ++j)&lt;br /&gt;
                centroids[i][j] /= allden[i];&lt;br /&gt;
        // calculate distances and probabilities, check stop conditions&lt;br /&gt;
        double err = 0.0;&lt;br /&gt;
        for (int i = rank; i &amp;lt; n; i+=size)&lt;br /&gt;
            for (int j = 0; j &amp;lt; n_cluster; ++j){&lt;br /&gt;
                for (int k = 0; k &amp;lt; x_dim; ++k)&lt;br /&gt;
                    dist[i][j] += (x[i][k] - centroids[j][k]) * (x[i][k] - centroids[j][k]);&lt;br /&gt;
                double w_prev = w[i][j];&lt;br /&gt;
                for (int k = 0; k &amp;lt; n_cluster; ++k)&lt;br /&gt;
                    w[i][j] += dist[i][j] / dist[i][k];&lt;br /&gt;
                w[i][j] = 1.0 / pow(w[i][j], 1.0 / (m - 1));&lt;br /&gt;
                err = fmax(err, abs(w_prev - w[i][j]));&lt;br /&gt;
            }&lt;br /&gt;
        return err;&lt;br /&gt;
    }&lt;br /&gt;
    int FCM(){&lt;br /&gt;
        *total_err = eps+1;&lt;br /&gt;
        int cur_iter = 0;&lt;br /&gt;
        while (cur_iter &amp;lt; max_iter &amp;amp;&amp;amp; *total_err &amp;gt; eps){&lt;br /&gt;
            *err = make_iteration();&lt;br /&gt;
            MPI_Allreduce(err, total_err, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);&lt;br /&gt;
            cur_iter++;&lt;br /&gt;
        }&lt;br /&gt;
        return cur_iter;&lt;br /&gt;
    }&lt;br /&gt;
    void clearMatrix(double ** matr, int r, int c){&lt;br /&gt;
        for (int i = 0; i &amp;lt; r; ++i){&lt;br /&gt;
            delete [] matr[i];&lt;br /&gt;
        }&lt;br /&gt;
        delete [] matr;&lt;br /&gt;
    }&lt;br /&gt;
    int memory_free(){&lt;br /&gt;
        clearMatrix(x, n, x_dim);&lt;br /&gt;
        clearMatrix(centroids, n_cluster, x_dim);&lt;br /&gt;
        clearMatrix(w, n_cluster, n);&lt;br /&gt;
        clearMatrix(num, n_cluster, x_dim);&lt;br /&gt;
        clearMatrix(dist, n, n_cluster);&lt;br /&gt;
        delete [] den;&lt;br /&gt;
        delete [] allden;&lt;br /&gt;
        delete err;&lt;br /&gt;
        delete total_err;&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
    int main(int argc, char **argv){&lt;br /&gt;
        MPI_Init(&amp;amp;argc, &amp;amp;argv);&lt;br /&gt;
        MPI_Comm_size(MPI_COMM_WORLD, &amp;amp;size);&lt;br /&gt;
        MPI_Comm_rank(MPI_COMM_WORLD, &amp;amp;rank);&lt;br /&gt;
        int n_repeat = strtol(argv[1], NULL, 10);&lt;br /&gt;
        int nx_min = strtol(argv[2], NULL, 10);&lt;br /&gt;
        int nx_max = strtol(argv[3], NULL, 10);&lt;br /&gt;
        int step = strtol(argv[4], NULL, 10);&lt;br /&gt;
        x_dim = strtol(argv[5], NULL, 10);&lt;br /&gt;
        m = strtod(argv[6], NULL);&lt;br /&gt;
        n_cluster = strtol(argv[7], NULL, 10);&lt;br /&gt;
        max_iter = strtol(argv[8], NULL, 10);&lt;br /&gt;
        eps = strtod(argv[9], NULL);&lt;br /&gt;
        //for all input matrix sizes&lt;br /&gt;
        for (n = nx_min; n &amp;lt;= nx_max; n += step){&lt;br /&gt;
            double start, finish, time_elapsed_iter=0;&lt;br /&gt;
            int total_iterations = 0;&lt;br /&gt;
            //repeat for getting mean value&lt;br /&gt;
            for (int i = 0; i &amp;lt; n_repeat; ++i) {&lt;br /&gt;
                generate_data();&lt;br /&gt;
                MPI_Barrier(MPI_COMM_WORLD);&lt;br /&gt;
                start = MPI_Wtime();&lt;br /&gt;
                total_iterations += FCM();&lt;br /&gt;
                finish = MPI_Wtime();&lt;br /&gt;
                memory_free();&lt;br /&gt;
                time_elapsed_iter += (finish-start);&lt;br /&gt;
            }&lt;br /&gt;
            time_elapsed_iter /= total_iterations;&lt;br /&gt;
            if (rank == 0) {&lt;br /&gt;
                cout &amp;lt;&amp;lt; n &amp;lt;&amp;lt; &amp;quot; &amp;quot; &amp;lt;&amp;lt; size &amp;lt;&amp;lt; &amp;quot; &amp;quot; &amp;lt;&amp;lt; time_elapsed_iter &amp;lt;&amp;lt; endl;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        MPI_Finalize();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==Динамические характеристики и эффективность реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
==Выводы для классов архитектур==&lt;br /&gt;
&lt;br /&gt;
==Существующие реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
* Реализация алгоритма на POSTGRESQL: http://num-meth.srcc.msu.ru/zhurnal/tom_2012/pdf/v13r207.pdf&lt;br /&gt;
* Библиотека для MATLAB: http://www.mathworks.com/help/fuzzy/fcm.html (распространяется на коммерческой основе)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=21243</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=21243"/>
		<updated>2016-12-18T19:21:03Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|{{REVISIONUSER}}}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(Mdc^2i)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - количество итераций&lt;br /&gt;
| input_data         = &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt;, [количество наблюдений * размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt;, [количество наблюдений * количество кластеров]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;2i&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]] ([[#Вычислительное ядро алгоритма|1.3]]; [[#Схема реализации последовательного алгоритма|1.5]]; [[#Последовательная сложность алгоритма|1.6]]; [[#Информационный граф|1.7]]; [[#Масштабируемость алгоритма и его реализации|2.4]]; [[#Существующие реализации алгоритма|2.7]]), [[Участник:Yushin|Павел Юшин]] ([[#Общее описание алгоритма|1.1]]; [[#Математическое описание алгоритма|1.2]]; [[#Макроструктура алгоритма|1.4]]; [[#Ресурс параллелизма алгоритма|1.8]]; [[#Входные и выходные данные алгоритма|1.9]]; [[#Свойства алгоритма|1.10]])&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;[http://www.tandfonline.com/doi/abs/10.1080/01969727308546046 | J. C. Dunn. A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters. Journal of Cybernetics, volume 3,1973 - Issue 3, pp 32-57]&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов кластеризации, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров;&amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма будут отличать менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;[http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf | Нейский И.М. Классификация и сравнение методов кластеризации.// Интеллектуальные технологии и системы. Сборник учебно-методических работ и статей аспирантов и студентов. – М.: НОК «CLAIM», 2006. – Выпуск 8. – С. 130-142.]&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M&amp;lt;/math&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;0 &amp;lt; \sum_{i = 1}^M w_{ij} &amp;lt; M, j = 1, ..., c&amp;lt;/math&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда алгоритм принимает следующий вид:&lt;br /&gt;
&lt;br /&gt;
1) Задаем параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
2) Генерируем случайным образом матрицу нечеткого разбиения с учетом условий &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3) Рассчитываем центроиды (центры кластеров): &amp;lt;math&amp;gt;V_j = {{\sum_{i=1}^M w_{ij}^m * X_i} \over {\sum_{i=1}^M w_{ij}^m}}, j = 1, ..., c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Рассчитываем расстояния между объектами &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и центроидами:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_{ij} = {||X_i - V_j||}, i = 1,...,M; j = 1,...,c &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5) Пересчет элементов матрицы разбиения:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} &amp;gt;0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = {{1}\over {{ (\sum_{k=1}^c {{D_{ij}}\over{D_{ik}}} ) }^{2/(m-1)}}}, j = 1,...,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} =0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = \delta_{ij}, j = 1,...,c&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\delta_{ij}&amp;lt;/math&amp;gt; - символ Кронекера&lt;br /&gt;
&lt;br /&gt;
6) Если &amp;lt;math&amp;gt;|| F - F^{*} || &amp;lt; \varepsilon &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;F^{*}&amp;lt;/math&amp;gt; - матрица нечеткого разбиения предыдущей итерации, то идем далее, иначе возвращаемся на пункт 3.&lt;br /&gt;
&lt;br /&gt;
7) Конец.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром алгоритма являются следующие пункты:&lt;br /&gt;
&lt;br /&gt;
* Поиск &amp;lt;math&amp;gt;V_j&amp;lt;/math&amp;gt; - расчет центроидов (пункт 3 алгоритма)&lt;br /&gt;
* Нахождение &amp;lt;math&amp;gt;D_{ij}&amp;lt;/math&amp;gt; - расстояний между объектами (пункт 4 алгоритма)&lt;br /&gt;
* Пересчет &amp;lt;math&amp;gt;w_{ij}&amp;lt;/math&amp;gt; - элементов матрицы разбиения (пункт 5 алгоритма)&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Основные шаги при реализации алгоритма&lt;br /&gt;
*	Генерация случайной матрицы размера &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на где &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;, проверка условий&lt;br /&gt;
*	Расчет центроидов – по сути, скалярное произведение с нормировкой&lt;br /&gt;
*	Расчет расстояний – в общепринятом случае является скалярным произведением&lt;br /&gt;
*	Пересчет матрицы – по сути, скалярное произведение&lt;br /&gt;
*	Проверка условий останова – вычисление нормы&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
    float ** FuzzyCMeans (float** X, c, m, eps){&lt;br /&gt;
        n = X.size();&lt;br /&gt;
        r = X[0].size();&lt;br /&gt;
        centers = generateZeroFill(c, r)&lt;br /&gt;
        Wprev = genetateRandFill(n, c);&lt;br /&gt;
        W = Wprev;&lt;br /&gt;
        while (true){&lt;br /&gt;
            // обновляем центры кластеров &lt;br /&gt;
            for (int i=0; i&amp;lt;c; i++){&lt;br /&gt;
                float * num = new float []();&lt;br /&gt;
                float den = 0;&lt;br /&gt;
                for (int j=0; j&amp;lt;n; j++){&lt;br /&gt;
                    num += pow(W[j][i], m) * X[j];&lt;br /&gt;
                    den+=pow(W[j][i], m);&lt;br /&gt;
                }&lt;br /&gt;
                centers[i] = num / den;&lt;br /&gt;
            }&lt;br /&gt;
            //обновляем вероятности W и считаем расстояние между матрицами W и Wprev&lt;br /&gt;
            float max_diff = 0;&lt;br /&gt;
            for (int i=0; i&amp;lt;n; i++)&lt;br /&gt;
                for (int j=0; j&amp;lt;c; j++){&lt;br /&gt;
                    total = 0;&lt;br /&gt;
                    for (int m=0; m&amp;lt;с; m++)&lt;br /&gt;
                        total += pow(distance(X[i], centers[j]) / distance(X[i], centers[m]), 2/(m-1));&lt;br /&gt;
                    W[i][j] = 1/total;&lt;br /&gt;
                    max_diff = max(abs(Wprev[i][j]-W[i][j]), max_diff);&lt;br /&gt;
                    Wprev[i][j] = W[i][j];&lt;br /&gt;
               }               &lt;br /&gt;
           if (max_diff &amp;lt; eps):                &lt;br /&gt;
                break;&lt;br /&gt;
        }&lt;br /&gt;
        return W;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Последовательная сложность алгоритма состоит из сложности каждой итерации умноженной на их количество. Так как число итераций заранее неизвестно и зависит от входных параметров, рассмотрим сложность на каждой итерации. Наибольшую сложность представляет собой пересчет матрицы, сложность которого &amp;lt;math&amp;gt;O(c^2 nd)&amp;lt;/math&amp;gt; (по сравнению со сложностью &amp;lt;math&amp;gt;O(cnd)&amp;lt;/math&amp;gt; расчета расстояний, вычисления центроидов и проверки условия останова). Итого общая сложность алгоритма &amp;lt;math&amp;gt;O(c^2 ndi)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
Информационный граф представлен на рисунке ниже.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 1, 2, совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз для каждого кластера. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 1&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 2&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m*X_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем вектор размера &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; и матрицу размера &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;. &lt;br /&gt;
Далее совершаем поэлементное сложение векторов и матриц соответственно, а затем делим каждый столбец в матрице на соответствующий элемент в векторе.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй ярус&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 3, 4, 5 также совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 3&#039;&#039;&#039;: обновление значения &amp;lt;math&amp;gt;w_{ij}&amp;lt;/math&amp;gt; по указанной в разделе 1.2 в пункте 5 формуле.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 4&#039;&#039;&#039;: &amp;lt;math&amp;gt;maximum = max(|w_{ij} - w_{ij}^{prev}|, maximum)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 5&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^{prev} = w_{ij}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем число &amp;lt;math&amp;gt;maximum&amp;lt;/math&amp;gt;. Далее находим максимальное значение из полученных величин для каждой ветки. Затем проверяем условие останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:Scheme3.JPG]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельная сложность алгоритма: &amp;lt;math&amp;gt;M*c^2*i&amp;lt;/math&amp;gt;. Такая сложность получается за счет распараллеливания на каждом ярусе &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; операций. Иерархическая структура параллелизма подробно описана в [[#Информационный граф|п.1.7]].&lt;br /&gt;
&lt;br /&gt;
В алгоритме не возникает скошенного параллелизма.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Входные данные алгоритма: набор векторов &amp;lt;math&amp;gt;x_i&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i = 1,...,M&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
* Объем входных данных: &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt; , [количество наблюдений * размерность].&lt;br /&gt;
* Выходные данные алгоритма: матрица вероятностей принадлежности векторов кластерам &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Объем выходных данных: &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt; , [количество наблюдений * количество кластеров].&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной формы алгоритма: &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;&lt;br /&gt;
* Вычислительная мощность: &amp;lt;math&amp;gt;{dc^2i} \over {c+d}&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Устойчивость: алгоритм не является устойчивым, поэтому существует много исследований о том, как первоначально выбрать параметры кластеризации.&lt;br /&gt;
* Сбалансированность: в данном алгоритме операция умножения доминирует над операцией сложения. Операции между параллельными ветвями сбалансированны.&lt;br /&gt;
* Детерминированность: алгоритм не является детерминированным, так как матрица нечеткого разбиение генерируется произвольно.&lt;br /&gt;
* Степень исхода вершины информационного графа ( для одной интерации): 2 (3 - с учетом, если выходные данные пошли на следующую итерацию).&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма = &lt;br /&gt;
&lt;br /&gt;
==Особенности реализации последовательного алгоритма==&lt;br /&gt;
&lt;br /&gt;
==Локальность данных и вычислений==&lt;br /&gt;
&lt;br /&gt;
==Возможные способы и особенности параллельной реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
Проведём исследование масштабируемости параллельной реализации нечеткого алгоритма С-средних. &lt;br /&gt;
Исследование проводилось на суперкомпьютере &amp;quot;Ломоносов&amp;quot;&amp;lt;ref name=&amp;quot;Lom&amp;quot;&amp;gt;Воеводин Вл., Жуматий С., Соболев С., Антонов А., Брызгалов П., Никитенко Д., Стефанов К., Воеводин Вад. Практика суперкомпьютера «Ломоносов» // Открытые системы, 2012, N 7, С. 36-39.&amp;lt;/ref&amp;gt; [http://parallel.ru/cluster Суперкомпьютерного комплекса Московского университета]. &lt;br /&gt;
Была исследована собственная параллельная реализация алгоритма, написанная на языке C++ с использованием стандарта MPI. Сборка программы производилась при помощи компилятора компании Intel версии 13.1.0 с использованием библиотеки intelMPI версии 4.1.0 . Расчеты проводились в разделе test на узлах со следующими характеристиками: количество GPU - 0, количество ядер - 8 ядер архитектуры x86, количество памяти - 12 Гб.&lt;br /&gt;
&lt;br /&gt;
Набор и границы значений изменяемых [[Глоссарий#Параметры запуска|параметров запуска]] реализации алгоритма: &lt;br /&gt;
&lt;br /&gt;
*	число процессоров [1 : 128];&lt;br /&gt;
*	размер матрицы [10000 : 80000].&lt;br /&gt;
&lt;br /&gt;
В результате проведённых экспериментов был получен следующий диапазон [[Глоссарий#Эффективность реализации|эффективности реализации]] алгоритма:&lt;br /&gt;
&lt;br /&gt;
*	минимальная эффективность реализации 0,33%;&lt;br /&gt;
*	максимальная эффективность реализации 9,4%.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
На следующих рисунках приведены графики [[Глоссарий#Производительность|производительности]] и  [[Глоссарий#Эффективность реализации|эффективности]] выбранной реализации в зависимости от изменяемых параметров запуска.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[file: FuzzyCMeansPerformance.png |thumb|center|700px|Рисунок 1. Параллельная реализация нечеткого алгоритма С-средних. Изменение производительности в зависимости от числа процессоров и размера матрицы.]]&lt;br /&gt;
[[file: FuzzyCMeansEfficiency2.png|thumb|center|700px|Рисунок 2. Параллельная реализация нечеткого алгоритма С-средних. Изменение эффективности реализации в зависимости от числа процессоров и размера матрицы.]]&lt;br /&gt;
&lt;br /&gt;
Построим оценки масштабируемости выбранной реализации нечеткого алгоритма С-средних:&lt;br /&gt;
*	По числу процессов: 0.007. При увеличении числа процессов эффективность на рассмотренной области изменений параметров запуска увеличивается.&lt;br /&gt;
*	По размеру задачи: -0.0016. При увеличении размера задачи эффективность уменьшается. &lt;br /&gt;
*	По двум направлениям: 0,000077. При рассмотрении увеличения как вычислительной сложности, так и числа процессов на всей рассмотренной области значений эффективность увеличивается, однако скорость увеличения эффективности небольшая.&lt;br /&gt;
&lt;br /&gt;
Была использована следующая реализация алгоритма. &lt;br /&gt;
&lt;br /&gt;
    #include &amp;lt;mpi.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;iostream&amp;gt;&lt;br /&gt;
    #include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;math.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;string.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;time.h&amp;gt;&lt;br /&gt;
    using namespace std;&lt;br /&gt;
    double **x; //input matrix of size (n x x_dim)&lt;br /&gt;
    int n;&lt;br /&gt;
    int x_dim;&lt;br /&gt;
    double **centroids; //cluster centroids matrix of size (n_cluster x x_dim)&lt;br /&gt;
    int n_cluster; // number of clusters&lt;br /&gt;
    double **w; //probability matrix of size (n x n_cluster)&lt;br /&gt;
    double **dist; //distances matrix of size (n x n_cluster)&lt;br /&gt;
    double eps; //max error&lt;br /&gt;
    double m; //parameter of algo&lt;br /&gt;
    int max_iter; // max num of iterations&lt;br /&gt;
    double **num;&lt;br /&gt;
    double *den;&lt;br /&gt;
    double *allden;&lt;br /&gt;
    double *err;&lt;br /&gt;
    double *total_err;&lt;br /&gt;
    int rank, size;&lt;br /&gt;
    double ** generateZerosMatrix(int r, int c){&lt;br /&gt;
        double ** arr = new double* [r];&lt;br /&gt;
        for (int i = 0; i &amp;lt; r; ++i){&lt;br /&gt;
            arr[i] = new double[c]();&lt;br /&gt;
        }&lt;br /&gt;
        return arr;&lt;br /&gt;
    }&lt;br /&gt;
    int generate_data()&lt;br /&gt;
    {&lt;br /&gt;
        //generate matrix&lt;br /&gt;
        x = generateZerosMatrix(n, x_dim);&lt;br /&gt;
        centroids = generateZerosMatrix(n_cluster, x_dim);&lt;br /&gt;
        w = generateZerosMatrix(n, n_cluster);&lt;br /&gt;
        dist = generateZerosMatrix(n, n_cluster);&lt;br /&gt;
        num = generateZerosMatrix(n_cluster, x_dim);&lt;br /&gt;
        //generate vectors&lt;br /&gt;
        den = new double [n_cluster]();&lt;br /&gt;
        allden = new double [n_cluster]();&lt;br /&gt;
        //for stopping algorithm&lt;br /&gt;
        err = new double;&lt;br /&gt;
        total_err = new double;&lt;br /&gt;
        srand(time(0));&lt;br /&gt;
        //initialize w randomly with restrictions&lt;br /&gt;
        for (int i = 0; i &amp;lt; n; ++i){&lt;br /&gt;
            double sum = 0;&lt;br /&gt;
            for (int j = 0; j &amp;lt; n_cluster; ++j){&lt;br /&gt;
                w[i][j] = rand();&lt;br /&gt;
                sum += w[i][j];&lt;br /&gt;
            }&lt;br /&gt;
            for (int j = 0; j &amp;lt; n_cluster; ++j){&lt;br /&gt;
                w[i][j] /= sum;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        //initialize x randomly&lt;br /&gt;
        for (int i = 0; i &amp;lt; n; ++i)&lt;br /&gt;
            for (int j = 0; j &amp;lt; x_dim; ++j)&lt;br /&gt;
                x[i][j] = rand();&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
    double make_iteration() {&lt;br /&gt;
        // calculate centroids centers&lt;br /&gt;
        for (int i = rank; i &amp;lt; n; i+=size)&lt;br /&gt;
            for (int j = 0; j &amp;lt; n_cluster; ++j){&lt;br /&gt;
                double mu = pow(w[i][j], m);&lt;br /&gt;
                den[j] += mu;&lt;br /&gt;
                for (int k = 0; k &amp;lt; x_dim; ++k)&lt;br /&gt;
                    num[j][k] = mu * x[i][k];&lt;br /&gt;
            }&lt;br /&gt;
        MPI_Allreduce(den, allden, n_cluster, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);&lt;br /&gt;
        for (int j=0; j &amp;lt; n_cluster; ++j)&lt;br /&gt;
            MPI_Allreduce(num[j], centroids[j], x_dim, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);&lt;br /&gt;
        for (int i = 0; i &amp;lt; n_cluster; ++i)&lt;br /&gt;
            for (int j = 0; j &amp;lt; x_dim; ++j)&lt;br /&gt;
                centroids[i][j] /= allden[i];&lt;br /&gt;
        // calculate distances and probabilities, check stop conditions&lt;br /&gt;
        double err = 0.0;&lt;br /&gt;
        for (int i = rank; i &amp;lt; n; i+=size)&lt;br /&gt;
            for (int j = 0; j &amp;lt; n_cluster; ++j){&lt;br /&gt;
                for (int k = 0; k &amp;lt; x_dim; ++k)&lt;br /&gt;
                    dist[i][j] += (x[i][k] - centroids[j][k]) * (x[i][k] - centroids[j][k]);&lt;br /&gt;
                double w_prev = w[i][j];&lt;br /&gt;
                for (int k = 0; k &amp;lt; n_cluster; ++k)&lt;br /&gt;
                    w[i][j] += dist[i][j] / dist[i][k];&lt;br /&gt;
                w[i][j] = 1.0 / pow(w[i][j], 1.0 / (m - 1));&lt;br /&gt;
                err = fmax(err, abs(w_prev - w[i][j]));&lt;br /&gt;
            }&lt;br /&gt;
        return err;&lt;br /&gt;
    }&lt;br /&gt;
    int FCM(){&lt;br /&gt;
        *total_err = eps+1;&lt;br /&gt;
        int cur_iter = 0;&lt;br /&gt;
        while (cur_iter &amp;lt; max_iter &amp;amp;&amp;amp; *total_err &amp;gt; eps){&lt;br /&gt;
            *err = make_iteration();&lt;br /&gt;
            MPI_Allreduce(err, total_err, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);&lt;br /&gt;
            cur_iter++;&lt;br /&gt;
        }&lt;br /&gt;
        return cur_iter;&lt;br /&gt;
    }&lt;br /&gt;
    void clearMatrix(double ** matr, int r, int c){&lt;br /&gt;
        for (int i = 0; i &amp;lt; r; ++i){&lt;br /&gt;
            delete [] matr[i];&lt;br /&gt;
        }&lt;br /&gt;
        delete [] matr;&lt;br /&gt;
    }&lt;br /&gt;
    int memory_free(){&lt;br /&gt;
        clearMatrix(x, n, x_dim);&lt;br /&gt;
        clearMatrix(centroids, n_cluster, x_dim);&lt;br /&gt;
        clearMatrix(w, n_cluster, n);&lt;br /&gt;
        clearMatrix(num, n_cluster, x_dim);&lt;br /&gt;
        clearMatrix(dist, n, n_cluster);&lt;br /&gt;
        delete [] den;&lt;br /&gt;
        delete [] allden;&lt;br /&gt;
        delete err;&lt;br /&gt;
        delete total_err;&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
    int main(int argc, char **argv){&lt;br /&gt;
        MPI_Init(&amp;amp;argc, &amp;amp;argv);&lt;br /&gt;
        MPI_Comm_size(MPI_COMM_WORLD, &amp;amp;size);&lt;br /&gt;
        MPI_Comm_rank(MPI_COMM_WORLD, &amp;amp;rank);&lt;br /&gt;
        int n_repeat = strtol(argv[1], NULL, 10);&lt;br /&gt;
        int nx_min = strtol(argv[2], NULL, 10);&lt;br /&gt;
        int nx_max = strtol(argv[3], NULL, 10);&lt;br /&gt;
        int step = strtol(argv[4], NULL, 10);&lt;br /&gt;
        x_dim = strtol(argv[5], NULL, 10);&lt;br /&gt;
        m = strtod(argv[6], NULL);&lt;br /&gt;
        n_cluster = strtol(argv[7], NULL, 10);&lt;br /&gt;
        max_iter = strtol(argv[8], NULL, 10);&lt;br /&gt;
        eps = strtod(argv[9], NULL);&lt;br /&gt;
        //for all input matrix sizes&lt;br /&gt;
        for (n = nx_min; n &amp;lt;= nx_max; n += step){&lt;br /&gt;
            double start, finish, time_elapsed_iter=0;&lt;br /&gt;
            int total_iterations = 0;&lt;br /&gt;
            //repeat for getting mean value&lt;br /&gt;
            for (int i = 0; i &amp;lt; n_repeat; ++i) {&lt;br /&gt;
                generate_data();&lt;br /&gt;
                MPI_Barrier(MPI_COMM_WORLD);&lt;br /&gt;
                start = MPI_Wtime();&lt;br /&gt;
                total_iterations += FCM();&lt;br /&gt;
                finish = MPI_Wtime();&lt;br /&gt;
                memory_free();&lt;br /&gt;
                time_elapsed_iter += (finish-start);&lt;br /&gt;
            }&lt;br /&gt;
            time_elapsed_iter /= total_iterations;&lt;br /&gt;
            if (rank == 0) {&lt;br /&gt;
                cout &amp;lt;&amp;lt; n &amp;lt;&amp;lt; &amp;quot; &amp;quot; &amp;lt;&amp;lt; size &amp;lt;&amp;lt; &amp;quot; &amp;quot; &amp;lt;&amp;lt; time_elapsed_iter &amp;lt;&amp;lt; endl;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        MPI_Finalize();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==Динамические характеристики и эффективность реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
==Выводы для классов архитектур==&lt;br /&gt;
&lt;br /&gt;
==Существующие реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
* Реализация алгоритма на POSTGRESQL: http://num-meth.srcc.msu.ru/zhurnal/tom_2012/pdf/v13r207.pdf&lt;br /&gt;
* Библиотека для MATLAB: http://www.mathworks.com/help/fuzzy/fcm.html (распространяется на коммерческой основе)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=21242</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=21242"/>
		<updated>2016-12-18T19:18:57Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|{{REVISIONUSER}}}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(Mdc^2i)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - количество итераций&lt;br /&gt;
| input_data         = &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt;, [количество наблюдений * размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt;, [количество наблюдений * количество кластеров]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;2i&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]] ([[#Вычислительное ядро алгоритма|1.3]]; [[#Схема реализации последовательного алгоритма|1.5]]; [[#Последовательная сложность алгоритма|1.6]]; [[#Информационный граф|1.7]]; [[#Масштабируемость алгоритма и его реализации|2.4]]; [[#Существующие реализации алгоритма|2.7]]), [[Участник:Yushin|Павел Юшин]] ([[#Общее описание алгоритма|1.1]]; [[#Математическое описание алгоритма|1.2]]; [[#Макроструктура алгоритма|1.4]]; [[#Ресурс параллелизма алгоритма|1.8]]; [[#Входные и выходные данные алгоритма|1.9]]; [[#Свойства алгоритма|1.10]])&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;[http://www.tandfonline.com/doi/abs/10.1080/01969727308546046 | J. C. Dunn. A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters. Journal of Cybernetics, volume 3,1973 - Issue 3, pp 32-57]&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров;&amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма будут отличать менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;[http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf | Нейский И.М. Классификация и сравнение методов кластеризации.// Интеллектуальные технологии и системы. Сборник учебно-методических работ и статей аспирантов и студентов. – М.: НОК «CLAIM», 2006. – Выпуск 8. – С. 130-142.]&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M&amp;lt;/math&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;0 &amp;lt; \sum_{i = 1}^M w_{ij} &amp;lt; M, j = 1, ..., c&amp;lt;/math&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда алгоритм принимает следующий вид:&lt;br /&gt;
&lt;br /&gt;
1) Задаем параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
2) Генерируем случайным образом матрицу нечеткого разбиения с учетом условий &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3) Рассчитываем центроиды (центры кластеров): &amp;lt;math&amp;gt;V_j = {{\sum_{i=1}^M w_{ij}^m * X_i} \over {\sum_{i=1}^M w_{ij}^m}}, j = 1, ..., c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Рассчитываем расстояния между объектами &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и центроидами:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_{ij} = {||X_i - V_j||}, i = 1,...,M; j = 1,...,c &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5) Пересчет элементов матрицы разбиения:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} &amp;gt;0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = {{1}\over {{ (\sum_{k=1}^c {{D_{ij}}\over{D_{ik}}} ) }^{2/(m-1)}}}, j = 1,...,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} =0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = \delta_{ij}, j = 1,...,c&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\delta_{ij}&amp;lt;/math&amp;gt; - символ Кронекера&lt;br /&gt;
&lt;br /&gt;
6) Если &amp;lt;math&amp;gt;|| F - F^{*} || &amp;lt; \varepsilon &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;F^{*}&amp;lt;/math&amp;gt; - матрица нечеткого разбиения предыдущей итерации, то идем далее, иначе возвращаемся на пункт 3.&lt;br /&gt;
&lt;br /&gt;
7) Конец.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром алгоритма являются следующие пункты:&lt;br /&gt;
&lt;br /&gt;
* Поиск &amp;lt;math&amp;gt;V_j&amp;lt;/math&amp;gt; - расчет центроидов (пункт 3 алгоритма)&lt;br /&gt;
* Нахождение &amp;lt;math&amp;gt;D_{ij}&amp;lt;/math&amp;gt; - расстояний между объектами (пункт 4 алгоритма)&lt;br /&gt;
* Пересчет &amp;lt;math&amp;gt;w_{ij}&amp;lt;/math&amp;gt; - элементов матрицы разбиения (пункт 5 алгоритма)&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Основные шаги при реализации алгоритма&lt;br /&gt;
*	Генерация случайной матрицы размера &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на где &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;, проверка условий&lt;br /&gt;
*	Расчет центроидов – по сути, скалярное произведение с нормировкой&lt;br /&gt;
*	Расчет расстояний – в общепринятом случае является скалярным произведением&lt;br /&gt;
*	Пересчет матрицы – по сути, скалярное произведение&lt;br /&gt;
*	Проверка условий останова – вычисление нормы&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
    float ** FuzzyCMeans (float** X, c, m, eps){&lt;br /&gt;
        n = X.size();&lt;br /&gt;
        r = X[0].size();&lt;br /&gt;
        centers = generateZeroFill(c, r)&lt;br /&gt;
        Wprev = genetateRandFill(n, c);&lt;br /&gt;
        W = Wprev;&lt;br /&gt;
        while (true){&lt;br /&gt;
            // обновляем центры кластеров &lt;br /&gt;
            for (int i=0; i&amp;lt;c; i++){&lt;br /&gt;
                float * num = new float []();&lt;br /&gt;
                float den = 0;&lt;br /&gt;
                for (int j=0; j&amp;lt;n; j++){&lt;br /&gt;
                    num += pow(W[j][i], m) * X[j];&lt;br /&gt;
                    den+=pow(W[j][i], m);&lt;br /&gt;
                }&lt;br /&gt;
                centers[i] = num / den;&lt;br /&gt;
            }&lt;br /&gt;
            //обновляем вероятности W и считаем расстояние между матрицами W и Wprev&lt;br /&gt;
            float max_diff = 0;&lt;br /&gt;
            for (int i=0; i&amp;lt;n; i++)&lt;br /&gt;
                for (int j=0; j&amp;lt;c; j++){&lt;br /&gt;
                    total = 0;&lt;br /&gt;
                    for (int m=0; m&amp;lt;с; m++)&lt;br /&gt;
                        total += pow(distance(X[i], centers[j]) / distance(X[i], centers[m]), 2/(m-1));&lt;br /&gt;
                    W[i][j] = 1/total;&lt;br /&gt;
                    max_diff = max(abs(Wprev[i][j]-W[i][j]), max_diff);&lt;br /&gt;
                    Wprev[i][j] = W[i][j];&lt;br /&gt;
               }               &lt;br /&gt;
           if (max_diff &amp;lt; eps):                &lt;br /&gt;
                break;&lt;br /&gt;
        }&lt;br /&gt;
        return W;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Последовательная сложность алгоритма состоит из сложности каждой итерации умноженной на их количество. Так как число итераций заранее неизвестно и зависит от входных параметров, рассмотрим сложность на каждой итерации. Наибольшую сложность представляет собой пересчет матрицы, сложность которого &amp;lt;math&amp;gt;O(c^2 nd)&amp;lt;/math&amp;gt; (по сравнению со сложностью &amp;lt;math&amp;gt;O(cnd)&amp;lt;/math&amp;gt; расчета расстояний, вычисления центроидов и проверки условия останова). Итого общая сложность алгоритма &amp;lt;math&amp;gt;O(c^2 ndi)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
Информационный граф представлен на рисунке ниже.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 1, 2, совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз для каждого кластера. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 1&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 2&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m*X_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем вектор размера &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; и матрицу размера &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;. &lt;br /&gt;
Далее совершаем поэлементное сложение векторов и матриц соответственно, а затем делим каждый столбец в матрице на соответствующий элемент в векторе.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй ярус&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 3, 4, 5 также совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 3&#039;&#039;&#039;: обновление значения &amp;lt;math&amp;gt;w_{ij}&amp;lt;/math&amp;gt; по указанной в разделе 1.2 в пункте 5 формуле.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 4&#039;&#039;&#039;: &amp;lt;math&amp;gt;maximum = max(|w_{ij} - w_{ij}^{prev}|, maximum)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 5&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^{prev} = w_{ij}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем число &amp;lt;math&amp;gt;maximum&amp;lt;/math&amp;gt;. Далее находим максимальное значение из полученных величин для каждой ветки. Затем проверяем условие останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:Scheme3.JPG]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельная сложность алгоритма: &amp;lt;math&amp;gt;M*c^2*i&amp;lt;/math&amp;gt;. Такая сложность получается за счет распараллеливания на каждом ярусе &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; операций. Иерархическая структура параллелизма подробно описана в [[#Информационный граф|п.1.7]].&lt;br /&gt;
&lt;br /&gt;
В алгоритме не возникает скошенного параллелизма.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Входные данные алгоритма: набор векторов &amp;lt;math&amp;gt;x_i&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i = 1,...,M&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
* Объем входных данных: &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt; , [количество наблюдений * размерность].&lt;br /&gt;
* Выходные данные алгоритма: матрица вероятностей принадлежности векторов кластерам &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Объем выходных данных: &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt; , [количество наблюдений * количество кластеров].&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной формы алгоритма: &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;&lt;br /&gt;
* Вычислительная мощность: &amp;lt;math&amp;gt;{dc^2i} \over {c+d}&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Устойчивость: алгоритм не является устойчивым, поэтому существует много исследований о том, как первоначально выбрать параметры кластеризации.&lt;br /&gt;
* Сбалансированность: в данном алгоритме операция умножения доминирует над операцией сложения. Операции между параллельными ветвями сбалансированны.&lt;br /&gt;
* Детерминированность: алгоритм не является детерминированным, так как матрица нечеткого разбиение генерируется произвольно.&lt;br /&gt;
* Степень исхода вершины информационного графа ( для одной интерации): 2 (3 - с учетом, если выходные данные пошли на следующую итерацию).&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма = &lt;br /&gt;
&lt;br /&gt;
==Особенности реализации последовательного алгоритма==&lt;br /&gt;
&lt;br /&gt;
==Локальность данных и вычислений==&lt;br /&gt;
&lt;br /&gt;
==Возможные способы и особенности параллельной реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
Проведём исследование масштабируемости параллельной реализации нечеткого алгоритма С-средних. &lt;br /&gt;
Исследование проводилось на суперкомпьютере &amp;quot;Ломоносов&amp;quot;&amp;lt;ref name=&amp;quot;Lom&amp;quot;&amp;gt;Воеводин Вл., Жуматий С., Соболев С., Антонов А., Брызгалов П., Никитенко Д., Стефанов К., Воеводин Вад. Практика суперкомпьютера «Ломоносов» // Открытые системы, 2012, N 7, С. 36-39.&amp;lt;/ref&amp;gt; [http://parallel.ru/cluster Суперкомпьютерного комплекса Московского университета]. &lt;br /&gt;
Была исследована собственная параллельная реализация алгоритма, написанная на языке C++ с использованием стандарта MPI. Сборка программы производилась при помощи компилятора компании Intel версии 13.1.0 с использованием библиотеки intelMPI версии 4.1.0 . Расчеты проводились в разделе test на узлах со следующими характеристиками: количество GPU - 0, количество ядер - 8 ядер архитектуры x86, количество памяти - 12 Гб.&lt;br /&gt;
&lt;br /&gt;
Набор и границы значений изменяемых [[Глоссарий#Параметры запуска|параметров запуска]] реализации алгоритма: &lt;br /&gt;
&lt;br /&gt;
*	число процессоров [1 : 128];&lt;br /&gt;
*	размер матрицы [10000 : 80000].&lt;br /&gt;
&lt;br /&gt;
В результате проведённых экспериментов был получен следующий диапазон [[Глоссарий#Эффективность реализации|эффективности реализации]] алгоритма:&lt;br /&gt;
&lt;br /&gt;
*	минимальная эффективность реализации 0,33%;&lt;br /&gt;
*	максимальная эффективность реализации 9,4%.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
На следующих рисунках приведены графики [[Глоссарий#Производительность|производительности]] и  [[Глоссарий#Эффективность реализации|эффективности]] выбранной реализации в зависимости от изменяемых параметров запуска.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[file: FuzzyCMeansPerformance.png |thumb|center|700px|Рисунок 1. Параллельная реализация нечеткого алгоритма С-средних. Изменение производительности в зависимости от числа процессоров и размера матрицы.]]&lt;br /&gt;
[[file: FuzzyCMeansEfficiency2.png|thumb|center|700px|Рисунок 2. Параллельная реализация нечеткого алгоритма С-средних. Изменение эффективности реализации в зависимости от числа процессоров и размера матрицы.]]&lt;br /&gt;
&lt;br /&gt;
Построим оценки масштабируемости выбранной реализации нечеткого алгоритма С-средних:&lt;br /&gt;
*	По числу процессов: 0.007. При увеличении числа процессов эффективность на рассмотренной области изменений параметров запуска увеличивается.&lt;br /&gt;
*	По размеру задачи: -0.0016. При увеличении размера задачи эффективность уменьшается. &lt;br /&gt;
*	По двум направлениям: 0,000077. При рассмотрении увеличения как вычислительной сложности, так и числа процессов на всей рассмотренной области значений эффективность увеличивается, однако скорость увеличения эффективности небольшая.&lt;br /&gt;
&lt;br /&gt;
Была использована следующая реализация алгоритма. &lt;br /&gt;
&lt;br /&gt;
    #include &amp;lt;mpi.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;iostream&amp;gt;&lt;br /&gt;
    #include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;math.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;string.h&amp;gt;&lt;br /&gt;
    #include &amp;lt;time.h&amp;gt;&lt;br /&gt;
    using namespace std;&lt;br /&gt;
    double **x; //input matrix of size (n x x_dim)&lt;br /&gt;
    int n;&lt;br /&gt;
    int x_dim;&lt;br /&gt;
    double **centroids; //cluster centroids matrix of size (n_cluster x x_dim)&lt;br /&gt;
    int n_cluster; // number of clusters&lt;br /&gt;
    double **w; //probability matrix of size (n x n_cluster)&lt;br /&gt;
    double **dist; //distances matrix of size (n x n_cluster)&lt;br /&gt;
    double eps; //max error&lt;br /&gt;
    double m; //parameter of algo&lt;br /&gt;
    int max_iter; // max num of iterations&lt;br /&gt;
    double **num;&lt;br /&gt;
    double *den;&lt;br /&gt;
    double *allden;&lt;br /&gt;
    double *err;&lt;br /&gt;
    double *total_err;&lt;br /&gt;
    int rank, size;&lt;br /&gt;
    double ** generateZerosMatrix(int r, int c){&lt;br /&gt;
        double ** arr = new double* [r];&lt;br /&gt;
        for (int i = 0; i &amp;lt; r; ++i){&lt;br /&gt;
            arr[i] = new double[c]();&lt;br /&gt;
        }&lt;br /&gt;
        return arr;&lt;br /&gt;
    }&lt;br /&gt;
    int generate_data()&lt;br /&gt;
    {&lt;br /&gt;
        //generate matrix&lt;br /&gt;
        x = generateZerosMatrix(n, x_dim);&lt;br /&gt;
        centroids = generateZerosMatrix(n_cluster, x_dim);&lt;br /&gt;
        w = generateZerosMatrix(n, n_cluster);&lt;br /&gt;
        dist = generateZerosMatrix(n, n_cluster);&lt;br /&gt;
        num = generateZerosMatrix(n_cluster, x_dim);&lt;br /&gt;
        //generate vectors&lt;br /&gt;
        den = new double [n_cluster]();&lt;br /&gt;
        allden = new double [n_cluster]();&lt;br /&gt;
        //for stopping algorithm&lt;br /&gt;
        err = new double;&lt;br /&gt;
        total_err = new double;&lt;br /&gt;
        srand(time(0));&lt;br /&gt;
        //initialize w randomly with restrictions&lt;br /&gt;
        for (int i = 0; i &amp;lt; n; ++i){&lt;br /&gt;
            double sum = 0;&lt;br /&gt;
            for (int j = 0; j &amp;lt; n_cluster; ++j){&lt;br /&gt;
                w[i][j] = rand();&lt;br /&gt;
                sum += w[i][j];&lt;br /&gt;
            }&lt;br /&gt;
            for (int j = 0; j &amp;lt; n_cluster; ++j){&lt;br /&gt;
                w[i][j] /= sum;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        //initialize x randomly&lt;br /&gt;
        for (int i = 0; i &amp;lt; n; ++i)&lt;br /&gt;
            for (int j = 0; j &amp;lt; x_dim; ++j)&lt;br /&gt;
                x[i][j] = rand();&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
    double make_iteration() {&lt;br /&gt;
        // calculate centroids centers&lt;br /&gt;
        for (int i = rank; i &amp;lt; n; i+=size)&lt;br /&gt;
            for (int j = 0; j &amp;lt; n_cluster; ++j){&lt;br /&gt;
                double mu = pow(w[i][j], m);&lt;br /&gt;
                den[j] += mu;&lt;br /&gt;
                for (int k = 0; k &amp;lt; x_dim; ++k)&lt;br /&gt;
                    num[j][k] = mu * x[i][k];&lt;br /&gt;
            }&lt;br /&gt;
        MPI_Allreduce(den, allden, n_cluster, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);&lt;br /&gt;
        for (int j=0; j &amp;lt; n_cluster; ++j)&lt;br /&gt;
            MPI_Allreduce(num[j], centroids[j], x_dim, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);&lt;br /&gt;
        for (int i = 0; i &amp;lt; n_cluster; ++i)&lt;br /&gt;
            for (int j = 0; j &amp;lt; x_dim; ++j)&lt;br /&gt;
                centroids[i][j] /= allden[i];&lt;br /&gt;
        // calculate distances and probabilities, check stop conditions&lt;br /&gt;
        double err = 0.0;&lt;br /&gt;
        for (int i = rank; i &amp;lt; n; i+=size)&lt;br /&gt;
            for (int j = 0; j &amp;lt; n_cluster; ++j){&lt;br /&gt;
                for (int k = 0; k &amp;lt; x_dim; ++k)&lt;br /&gt;
                    dist[i][j] += (x[i][k] - centroids[j][k]) * (x[i][k] - centroids[j][k]);&lt;br /&gt;
                double w_prev = w[i][j];&lt;br /&gt;
                for (int k = 0; k &amp;lt; n_cluster; ++k)&lt;br /&gt;
                    w[i][j] += dist[i][j] / dist[i][k];&lt;br /&gt;
                w[i][j] = 1.0 / pow(w[i][j], 1.0 / (m - 1));&lt;br /&gt;
                err = fmax(err, abs(w_prev - w[i][j]));&lt;br /&gt;
            }&lt;br /&gt;
        return err;&lt;br /&gt;
    }&lt;br /&gt;
    int FCM(){&lt;br /&gt;
        *total_err = eps+1;&lt;br /&gt;
        int cur_iter = 0;&lt;br /&gt;
        while (cur_iter &amp;lt; max_iter &amp;amp;&amp;amp; *total_err &amp;gt; eps){&lt;br /&gt;
            *err = make_iteration();&lt;br /&gt;
            MPI_Allreduce(err, total_err, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);&lt;br /&gt;
            cur_iter++;&lt;br /&gt;
        }&lt;br /&gt;
        return cur_iter;&lt;br /&gt;
    }&lt;br /&gt;
    void clearMatrix(double ** matr, int r, int c){&lt;br /&gt;
        for (int i = 0; i &amp;lt; r; ++i){&lt;br /&gt;
            delete [] matr[i];&lt;br /&gt;
        }&lt;br /&gt;
        delete [] matr;&lt;br /&gt;
    }&lt;br /&gt;
    int memory_free(){&lt;br /&gt;
        clearMatrix(x, n, x_dim);&lt;br /&gt;
        clearMatrix(centroids, n_cluster, x_dim);&lt;br /&gt;
        clearMatrix(w, n_cluster, n);&lt;br /&gt;
        clearMatrix(num, n_cluster, x_dim);&lt;br /&gt;
        clearMatrix(dist, n, n_cluster);&lt;br /&gt;
        delete [] den;&lt;br /&gt;
        delete [] allden;&lt;br /&gt;
        delete err;&lt;br /&gt;
        delete total_err;&lt;br /&gt;
        return 0;&lt;br /&gt;
    }&lt;br /&gt;
    int main(int argc, char **argv){&lt;br /&gt;
        MPI_Init(&amp;amp;argc, &amp;amp;argv);&lt;br /&gt;
        MPI_Comm_size(MPI_COMM_WORLD, &amp;amp;size);&lt;br /&gt;
        MPI_Comm_rank(MPI_COMM_WORLD, &amp;amp;rank);&lt;br /&gt;
        int n_repeat = strtol(argv[1], NULL, 10);&lt;br /&gt;
        int nx_min = strtol(argv[2], NULL, 10);&lt;br /&gt;
        int nx_max = strtol(argv[3], NULL, 10);&lt;br /&gt;
        int step = strtol(argv[4], NULL, 10);&lt;br /&gt;
        x_dim = strtol(argv[5], NULL, 10);&lt;br /&gt;
        m = strtod(argv[6], NULL);&lt;br /&gt;
        n_cluster = strtol(argv[7], NULL, 10);&lt;br /&gt;
        max_iter = strtol(argv[8], NULL, 10);&lt;br /&gt;
        eps = strtod(argv[9], NULL);&lt;br /&gt;
        //for all input matrix sizes&lt;br /&gt;
        for (n = nx_min; n &amp;lt;= nx_max; n += step){&lt;br /&gt;
            double start, finish, time_elapsed_iter=0;&lt;br /&gt;
            int total_iterations = 0;&lt;br /&gt;
            //repeat for getting mean value&lt;br /&gt;
            for (int i = 0; i &amp;lt; n_repeat; ++i) {&lt;br /&gt;
                generate_data();&lt;br /&gt;
                MPI_Barrier(MPI_COMM_WORLD);&lt;br /&gt;
                start = MPI_Wtime();&lt;br /&gt;
                total_iterations += FCM();&lt;br /&gt;
                finish = MPI_Wtime();&lt;br /&gt;
                memory_free();&lt;br /&gt;
                time_elapsed_iter += (finish-start);&lt;br /&gt;
            }&lt;br /&gt;
            time_elapsed_iter /= total_iterations;&lt;br /&gt;
            if (rank == 0) {&lt;br /&gt;
                cout &amp;lt;&amp;lt; n &amp;lt;&amp;lt; &amp;quot; &amp;quot; &amp;lt;&amp;lt; size &amp;lt;&amp;lt; &amp;quot; &amp;quot; &amp;lt;&amp;lt; time_elapsed_iter &amp;lt;&amp;lt; endl;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        MPI_Finalize();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
==Динамические характеристики и эффективность реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
==Выводы для классов архитектур==&lt;br /&gt;
&lt;br /&gt;
==Существующие реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
* Реализация алгоритма на POSTGRESQL: http://num-meth.srcc.msu.ru/zhurnal/tom_2012/pdf/v13r207.pdf&lt;br /&gt;
* Библиотека для MATLAB: http://www.mathworks.com/help/fuzzy/fcm.html (распространяется на коммерческой основе)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=16283</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=16283"/>
		<updated>2016-11-09T18:09:05Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(Mdc^2i)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - количество итераций&lt;br /&gt;
| input_data         = &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt;, [количество наблюдений * размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt;, [количество наблюдений * количество кластеров]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;2i&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]] ([[#Вычислительное ядро алгоритма|1.3]]; [[#Схема реализации последовательного алгоритма|1.5]]; [[#Последовательная сложность алгоритма|1.6]]; [[#Информационный граф|1.7]]; [[#Масштабируемость алгоритма и его реализации|2.4]]; [[#Существующие реализации алгоритма|2.7]]), [[Участник:Yushin|Павел Юшин]] ([[#Общее описание алгоритма|1.1]]; [[#Математическое описание алгоритма|1.2]]; [[#Макроструктура алгоритма|1.4]]; [[#Ресурс параллелизма алгоритма|1.8]]; [[#Входные и выходные данные алгоритма|1.9]]; [[#Свойства алгоритма|1.10]])&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;[http://www.tandfonline.com/doi/abs/10.1080/01969727308546046 | J. C. Dunn. A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters. Journal of Cybernetics, volume 3,1973 - Issue 3, pp 32-57]&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - экспоненциальный вес; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма будут отличать менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;[http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf | Нейский И.М. Классификация и сравнение методов кластеризации.// Интеллектуальные технологии и системы. Сборник учебно-методических работ и статей аспирантов и студентов. – М.: НОК «CLAIM», 2006. – Выпуск 8. – С. 130-142.]&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M&amp;lt;/math&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;0 &amp;lt; \sum_{i = 1}^M w_{ij} &amp;lt; M, j = 1, ..., c&amp;lt;/math&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда алгоритм принимает следующий вид:&lt;br /&gt;
&lt;br /&gt;
1) Задаем параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
2) Генерируем случайным образом матрицу нечеткого разбиения с учетом условий &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3) Рассчитываем центроиды (центры кластеров): &amp;lt;math&amp;gt;V_j = {{\sum_{i=1}^M w_{ij}^m * X_i} \over {\sum_{i=1}^M w_{ij}^m}}, j = 1, ..., c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Рассчитываем расстояния между объектами &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и центроидами:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_{ij} = {||X_i - V_j||}, i = 1,...,M; j = 1,...,c &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5) Пересчет элементов матрицы разбиения:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} &amp;gt;0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = {{1}\over {{ (\sum_{k=1}^c {{D_{ij}}\over{D_{ik}}} ) }^{2/(m-1)}}}, j = 1,...,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} =0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = \delta_{ij}, j = 1,...,c&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\delta_{ij}&amp;lt;/math&amp;gt; - символ Кронекера&lt;br /&gt;
&lt;br /&gt;
6) Если &amp;lt;math&amp;gt;|| F - F^{*} || &amp;lt; \varepsilon &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;F^{*}&amp;lt;/math&amp;gt; - матрица нечеткого разбиения предыдущей итерации, то идем далее, иначе возвращаемся на пункт 3.&lt;br /&gt;
&lt;br /&gt;
7) Конец.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром алгоритма являются следующие пункты:&lt;br /&gt;
&lt;br /&gt;
* Поиск &amp;lt;math&amp;gt;V_j&amp;lt;/math&amp;gt; - расчет центроидов (пункт 3 алгоритма)&lt;br /&gt;
* Нахождение &amp;lt;math&amp;gt;D_{ij}&amp;lt;/math&amp;gt; - расстояний между объектами (пункт 4 алгоритма)&lt;br /&gt;
* Пересчет &amp;lt;math&amp;gt;w_{ij}&amp;lt;/math&amp;gt; - элементов матрицы разбиения (пункт 5 алгоритма)&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Основные шаги при реализации алгоритма&lt;br /&gt;
*	Генерация случайной матрицы размера &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на где &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;, проверка условий&lt;br /&gt;
*	Расчет центроидов – по сути, скалярное произведение с нормировкой&lt;br /&gt;
*	Расчет расстояний – в общепринятом случае является скалярным произведением&lt;br /&gt;
*	Пересчет матрицы – по сути, скалярное произведение&lt;br /&gt;
*	Проверка условий останова – вычисление нормы&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
    float ** FuzzyCMeans (float** X, c, m, eps){&lt;br /&gt;
        n = X.size();&lt;br /&gt;
        r = X[0].size();&lt;br /&gt;
        centers = generateZeroFill(c, r)&lt;br /&gt;
        Wprev = genetateRandFill(n, c);&lt;br /&gt;
        W = Wprev;&lt;br /&gt;
        while (true){&lt;br /&gt;
            // обновляем центры кластеров &lt;br /&gt;
            for (int i=0; i&amp;lt;c; i++){&lt;br /&gt;
                float * num = new float []();&lt;br /&gt;
                float den = 0;&lt;br /&gt;
                for (int j=0; j&amp;lt;n; j++){&lt;br /&gt;
                    num += pow(W[j][i], m) * X[j];&lt;br /&gt;
                    den+=pow(W[j][i], m);&lt;br /&gt;
                }&lt;br /&gt;
                centers[i] = num / den;&lt;br /&gt;
            }&lt;br /&gt;
            //обновляем вероятности W и считаем расстояние между матрицами W и Wprev&lt;br /&gt;
            float max_diff = 0;&lt;br /&gt;
            for (int i=0; i&amp;lt;n; i++)&lt;br /&gt;
                for (int j=0; j&amp;lt;c; j++){&lt;br /&gt;
                    total = 0;&lt;br /&gt;
                    for (int m=0; m&amp;lt;с; m++)&lt;br /&gt;
                        total += pow(distance(X[i], centers[j]) / distance(X[i], centers[m]), 2/(m-1));&lt;br /&gt;
                    W[i][j] = 1/total;&lt;br /&gt;
                    max_diff = max(abs(Wprev[i][j]-W[i][j]), max_diff);&lt;br /&gt;
                    Wprev[i][j] = W[i][j];&lt;br /&gt;
               }               &lt;br /&gt;
           if (max_diff &amp;lt; eps):                &lt;br /&gt;
                break;&lt;br /&gt;
        }&lt;br /&gt;
        return W;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Последовательная сложность алгоритма состоит из сложности каждой итерации умноженной на их количество. Так как число итераций заранее неизвестно и зависит от входных параметров, рассмотрим сложность на каждой итерации. Наибольшую сложность представляет собой пересчет матрицы, сложность которого &amp;lt;math&amp;gt;O(c^2 nd)&amp;lt;/math&amp;gt; (по сравнению со сложностью &amp;lt;math&amp;gt;O(cnd)&amp;lt;/math&amp;gt; расчета расстояний, вычисления центроидов и проверки условия останова). Итого общая сложность алгоритма &amp;lt;math&amp;gt;O(c^2 ndi)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
Информационный граф представлен на рисунке ниже.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 1, 2, совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз для каждого кластера. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 1&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 2&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m*X_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем вектор размера &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; и матрицу размера &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;. &lt;br /&gt;
Далее совершаем поэлементное сложение векторов и матриц соответственно, а затем делим каждый столбец в матрице на соответствующий элемент в векторе.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй ярус&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 3, 4, 5 также совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 4&#039;&#039;&#039;: обновление значения &amp;lt;math&amp;gt;w_{ij}&amp;lt;/math&amp;gt; по указанной в разделе 1.2 в пункте 5 формуле.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 5&#039;&#039;&#039;: &amp;lt;math&amp;gt;maximum = max(|w_{ij} - w_{ij}^{prev}|, maximum)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 6&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^{prev} = w_{ij}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем число &amp;lt;math&amp;gt;maximum&amp;lt;/math&amp;gt;. Далее находим максимальное значение из полученных величин для каждой ветки. Затем проверяем условие останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:Scheme3.JPG]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельная сложность алгоритма: &amp;lt;math&amp;gt;M*c^2*i&amp;lt;/math&amp;gt;. Такая сложность получается за счет распараллеливания на каждом ярусе &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; операций. Иерархическая структура параллелизма подробно описана в [[#Информационный граф|п.1.7]].&lt;br /&gt;
&lt;br /&gt;
В алгоритме не возникает скошенного параллелизма.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Входные данные алгоритма: набор векторов &amp;lt;math&amp;gt;x_i&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i = 1,...,M&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
* Объем входных данных: &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt; , [количество наблюдений * размерность].&lt;br /&gt;
* Выходные данные алгоритма: матрица вероятностей принадлежности векторов кластерам &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Объем выходных данных: &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt; , [количество наблюдений * количество кластеров].&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной формы алгоритма: &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;&lt;br /&gt;
* Вычислительная мощность: &amp;lt;math&amp;gt;{dc^2i} \over {c+d}&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Устойчивость: алгоритм не является устойчивым, поэтому существует много исследований о том, как первоначально выбрать параметры кластеризации.&lt;br /&gt;
* Сбалансированность: в данном алгоритме операция умножения доминирует над операцией сложения. Операции между параллельными ветвями сбалансированны.&lt;br /&gt;
* Детерминированность: алгоритм не является детерминированным, так как матрица нечеткого разбиение генерируется произвольно.&lt;br /&gt;
* Степень исхода вершины информационного графа ( для одной интерации): 2 (3 - с учетом, если выходные данные пошли на следующую итерацию).&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма = &lt;br /&gt;
&lt;br /&gt;
==Особенности реализации последовательного алгоритма==&lt;br /&gt;
&lt;br /&gt;
==Локальность данных и вычислений==&lt;br /&gt;
&lt;br /&gt;
==Возможные способы и особенности параллельной реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
==Динамические характеристики и эффективность реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
==Выводы для классов архитектур==&lt;br /&gt;
&lt;br /&gt;
==Существующие реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
* Реализация алгоритма на POSTGRESQL: http://num-meth.srcc.msu.ru/zhurnal/tom_2012/pdf/v13r207.pdf&lt;br /&gt;
* Библиотека для MATLAB: http://www.mathworks.com/help/fuzzy/fcm.html (распространяется на коммерческой основе)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=16282</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=16282"/>
		<updated>2016-11-09T18:08:15Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(Mdc^2i)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - количество итераций&lt;br /&gt;
| input_data         = &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt;, [количество наблюдений * размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt;, [количество наблюдений * количество кластеров]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;2i&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]] ([[#Вычислительное ядро алгоритма|1.3]]; [[#Схема реализации последовательного алгоритма|1.5]]; [[#Последовательная сложность алгоритма|1.6]]; [[#Информационный граф|1.7]]; [[#Масштабируемость алгоритма и его реализации|2.4]]; [[#Существующие реализации алгоритма|2.7]]), [[Участник:Yushin|Павел Юшин]] ([[#Общее описание алгоритма|1.1]]; [[#Математическое описание алгоритма|1.2]]; [[#Макроструктура алгоритма|1.4]]; [[#Ресурс параллелизма алгоритма|1.8]]; [[#Входные и выходные данные алгоритма|1.9]]; [[#Свойства алгоритма|1.10]])&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;[http://www.tandfonline.com/doi/abs/10.1080/01969727308546046 | J. C. Dunn. A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters. Journal of Cybernetics, volume 3,1973 - Issue 3, pp 32-57]&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - экспоненциальный вес; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма будут отличать менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;[http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf | Нейский И.М. Классификация и сравнение методов кластеризации.// Интеллектуальные технологии и системы. Сборник учебно-методических работ и статей аспирантов и студентов. – М.: НОК «CLAIM», 2006. – Выпуск 8. – С. 130-142.]&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M&amp;lt;/math&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;0 &amp;lt; \sum_{i = 1}^M w_{ij} &amp;lt; M, j = 1, ..., c&amp;lt;/math&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда алгоритм принимает следующий вид:&lt;br /&gt;
&lt;br /&gt;
1) Задаем параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
2) Генерируем случайным образом матрицу нечеткого разбиения с учетом условий &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3) Рассчитываем центроиды (центры кластеров): &amp;lt;math&amp;gt;V_j = {{\sum_{i=1}^M w_{ij}^m * X_i} \over {\sum_{i=1}^M w_{ij}^m}}, j = 1, ..., c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Рассчитываем расстояния между объектами &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и центроидами:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_{ij} = {||X_i - V_j||}, i = 1,...,M; j = 1,...,c &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5) Пересчет элементов матрицы разбиения:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} &amp;gt;0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = {{1}\over {{ (\sum_{k=1}^c {{D_{ij}}\over{D_{ik}}} ) }^{2/(m-1)}}}, j = 1,...,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} =0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = \delta_{ij}, j = 1,...,c&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\delta_{ij}&amp;lt;/math&amp;gt; - символ Кронекера&lt;br /&gt;
&lt;br /&gt;
6) Если &amp;lt;math&amp;gt;|| F - F^{*} || &amp;lt; \varepsilon &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;F^{*}&amp;lt;/math&amp;gt; - матрица нечеткого разбиения предыдущей итерации, то идем далее, иначе возвращаемся на пункт 3.&lt;br /&gt;
&lt;br /&gt;
7) Конец.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром алгоритма являются следующие пункты:&lt;br /&gt;
&lt;br /&gt;
* Поиск &amp;lt;math&amp;gt;V_j&amp;lt;/math&amp;gt; - расчет центроидов (пункт 3 алгоритма)&lt;br /&gt;
* Нахождение &amp;lt;math&amp;gt;D_{ij}&amp;lt;/math&amp;gt; - расстояний между объектами (пункт 4 алгоритма)&lt;br /&gt;
* Пересчет &amp;lt;math&amp;gt;w_{ij}&amp;lt;/math&amp;gt; - элементов матрицы разбиения (пункт 5 алгоритма)&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Основные шаги при реализации алгоритма&lt;br /&gt;
*	Генерация случайной матрицы размера &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на где &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;, проверка условий&lt;br /&gt;
*	Расчет центроидов – по сути, скалярное произведение с нормировкой&lt;br /&gt;
*	Расчет расстояний – в общепринятом случае является скалярным произведением&lt;br /&gt;
*	Пересчет матрицы – по сути, скалярное произведение&lt;br /&gt;
*	Проверка условий останова – вычисление нормы&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
    float ** FuzzyCMeans (float** X, c, m, eps){&lt;br /&gt;
        n = X.size();&lt;br /&gt;
        r = X[0].size();&lt;br /&gt;
        centers = generateZeroFill(c, r)&lt;br /&gt;
        Wprev = genetateRandFill(n, c);&lt;br /&gt;
        W = Wprev;&lt;br /&gt;
        while (true){&lt;br /&gt;
            // обновляем центры кластеров &lt;br /&gt;
            for (int i=0; i&amp;lt;c; i++){&lt;br /&gt;
                float * num = new float []();&lt;br /&gt;
                float den = 0;&lt;br /&gt;
                for (int j=0; j&amp;lt;n; j++){&lt;br /&gt;
                    num += pow(W[j][i], m) * X[j];&lt;br /&gt;
                    den+=pow(W[j][i], m);&lt;br /&gt;
                }&lt;br /&gt;
                centers[i] = num / den;&lt;br /&gt;
            }&lt;br /&gt;
            //обновляем вероятности W и считаем расстояние между матрицами W и Wprev&lt;br /&gt;
            float max_diff = 0;&lt;br /&gt;
            for (int i=0; i&amp;lt;n; i++)&lt;br /&gt;
                for (int j=0; j&amp;lt;c; j++){&lt;br /&gt;
                    total = 0;&lt;br /&gt;
                    for (int m=0; m&amp;lt;с; m++)&lt;br /&gt;
                        total += pow(distance(X[i], centers[j]) / distance(X[i], centers[m]), 2/(m-1));&lt;br /&gt;
                    W[i][j] = 1/total;&lt;br /&gt;
                    max_diff = max(abs(Wprev[i][j]-W[i][j]), max_diff);&lt;br /&gt;
                    Wprev[i][j] = W[i][j];&lt;br /&gt;
               }               &lt;br /&gt;
           if (max_diff &amp;lt; eps):                &lt;br /&gt;
                break;&lt;br /&gt;
        }&lt;br /&gt;
        return W;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Последовательная сложность алгоритма состоит из сложности каждой итерации умноженной на их количество. Так как число итераций заранее неизвестно и зависит от входных параметров, рассмотрим сложность на каждой итерации. Наибольшую сложность представляет собой пересчет матрицы, сложность которого &amp;lt;math&amp;gt;O(c^2 nd)&amp;lt;/math&amp;gt; (по сравнению со сложностью &amp;lt;math&amp;gt;O(cnd)&amp;lt;/math&amp;gt; расчета расстояний, вычисления центроидов и проверки условия останова). Итого общая сложность алгоритма &amp;lt;math&amp;gt;O(c^2 ndi)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
Информационный граф представлен на рисунке ниже.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 1, 2, совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз для каждого кластера. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 1&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 2&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m*X_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем вектор размера &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; и матрицу размера &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;. &lt;br /&gt;
Далее совершаем поэлементное сложение векторов и матриц соответственно, а затем делим каждый столбец в матрице на соответствующий элемент в векторе.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй ярус&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 3, 4, 5 также совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 4&#039;&#039;&#039;: обновление значения &amp;lt;math&amp;gt;w_{ij}&amp;lt;/math&amp;gt; по указанной в разделе 1.2 в пункте 5 формуле.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 5&#039;&#039;&#039;: &amp;lt;math&amp;gt;maximum = max(|w_{ij} - w_{ij}^{prev}|, maximum)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 6&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^{prev} = w_{ij}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем число &amp;lt;math&amp;gt;maximum&amp;lt;/math&amp;gt;. Далее находим максимальное значение из полученных величин для каждой ветки. Затем проверяем условие останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:Scheme3.JPG]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельная сложность алгоритма: &amp;lt;math&amp;gt;M*c^2*i&amp;lt;/math&amp;gt;. Такая сложность получается за счет распараллеливания на каждом ярусе &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; операций. Иерархическая структура параллелизма подробно описана в [[#Информационный граф|п.1.7]].&lt;br /&gt;
&lt;br /&gt;
В алгоритме не возникает скошенного параллелизма.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Входные данные алгоритма: набор векторов &amp;lt;math&amp;gt;x_i&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i = 1,...,M&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
* Объем входных данных: &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt; , [количество наблюдений * размерность].&lt;br /&gt;
* Выходные данные алгоритма: матрица вероятностей принадлежности векторов кластерам &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Объем выходных данных: &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt; , [количество наблюдений * количество кластеров].&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной формы алгоритма: &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;&lt;br /&gt;
* Вычислительная мощность: &amp;lt;math&amp;gt;{dc^2i} \over {c+d}&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Устойчивость: алгоритм не является устойчивым, поэтому существует много исследований о том, как первоначально выбрать параметры кластеризации.&lt;br /&gt;
* Сбалансированность: в данном алгоритме операция умножения доминирует над операцией сложения. Операции между параллельными ветвями сбалансированны.&lt;br /&gt;
* Детерминированность: алгоритм не является детерминированным, так как матрица нечеткого разбиение генерируется произвольно.&lt;br /&gt;
* Степень исхода вершины информационного графа ( для одной интерации): 2 (3 - с учетом, если выходные данные пошли на следующую итерацию).&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма = &lt;br /&gt;
&lt;br /&gt;
==Особенности реализации последовательного алгоритма==&lt;br /&gt;
&lt;br /&gt;
==Локальность данных и вычислений==&lt;br /&gt;
&lt;br /&gt;
==Возможные способы и особенности параллельной реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
==Динамические характеристики и эффективность реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
==Выводы для классов архитектур==&lt;br /&gt;
&lt;br /&gt;
==Существующие реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
* Реализация алгоритма на POSTGRESQL: http://num-meth.srcc.msu.ru/zhurnal/tom_2012/pdf/v13r207.pdf&lt;br /&gt;
* Библиотека для MATLAB: http://www.mathworks.com/help/fuzzy/fcm.html (распространяется на коммерческой основе)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=15984</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=15984"/>
		<updated>2016-11-06T16:51:10Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(Mdc^2i)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - количество итераций&lt;br /&gt;
| input_data         = &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt;, [количество наблюдений * размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt;, [количество наблюдений * количество кластеров]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;2i&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]] ([[#Вычислительное ядро алгоритма|1.3]]; [[#Схема реализации последовательного алгоритма|1.5]]; [[#Последовательная сложность алгоритма|1.6]]; [[#Информационный граф|1.7]]; [[#Масштабируемость алгоритма и его реализации|2.4]]; [[#Существующие реализации алгоритма|2.7]]), [[Участник:Yushin|Павел Юшин]] ([[#Общее описание алгоритма|1.1]]; [[#Математическое описание алгоритма|1.2]]; [[#Макроструктура алгоритма|1.4]]; [[#Ресурс параллелизма алгоритма|1.8]]; [[#Входные и выходные данные алгоритма|1.9]]; [[#Свойства алгоритма|1.10]])&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;[http://www.tandfonline.com/doi/abs/10.1080/01969727308546046 | J. C. Dunn. A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters. Journal of Cybernetics, volume 3,1973 - Issue 3, pp 32-57]&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - экспоненциальный вес; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма будут отличать менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;[http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf | Нейский И.М. Классификация и сравнение методов кластеризации.]&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M&amp;lt;/math&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;0 &amp;lt; \sum_{i = 1}^M w_{ij} &amp;lt; M, j = 1, ..., c&amp;lt;/math&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда алгоритм принимает следующий вид:&lt;br /&gt;
&lt;br /&gt;
1) Задаем параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
2) Генерируем случайным образом матрицу нечеткого разбиения с учетом условий &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3) Рассчитываем центроиды (центры кластеров): &amp;lt;math&amp;gt;V_j = {{\sum_{i=1}^M w_{ij}^m * X_i} \over {\sum_{i=1}^M w_{ij}^m}}, j = 1, ..., c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Рассчитываем расстояния между объектами &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и центроидами:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_{ij} = {||X_i - V_j||}, i = 1,...,M; j = 1,...,c &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5) Пересчет элементов матрицы разбиения:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} &amp;gt;0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = {{1}\over {{ (\sum_{k=1}^c {{D_{ij}}\over{D_{ik}}} ) }^{2/(m-1)}}}, j = 1,...,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} =0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = \delta_{ij}, j = 1,...,c&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\delta_{ij}&amp;lt;/math&amp;gt; - символ Кронекера&lt;br /&gt;
&lt;br /&gt;
6) Если &amp;lt;math&amp;gt;|| F - F^{*} || &amp;lt; \varepsilon &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;F^{*}&amp;lt;/math&amp;gt; - матрица нечеткого разбиения предыдущей итерации, то идем далее, иначе возвращаемся на пункт 3.&lt;br /&gt;
&lt;br /&gt;
7) Конец.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром алгоритма являются следующие пункты:&lt;br /&gt;
&lt;br /&gt;
* Поиск &amp;lt;math&amp;gt;V_j&amp;lt;/math&amp;gt; - расчет центроидов (пункт 3 алгоритма)&lt;br /&gt;
* Нахождение &amp;lt;math&amp;gt;D_{ij}&amp;lt;/math&amp;gt; - расстояний между объектами (пункт 4 алгоритма)&lt;br /&gt;
* Пересчет &amp;lt;math&amp;gt;w_{ij}&amp;lt;/math&amp;gt; - элементов матрицы разбиения (пункт 5 алгоритма)&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Основные шаги при реализации алгоритма&lt;br /&gt;
*	Генерация случайной матрицы размера &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на где &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;, проверка условий&lt;br /&gt;
*	Расчет центроидов – по сути, скалярное произведение с нормировкой&lt;br /&gt;
*	Расчет расстояний – в общепринятом случае является скалярным произведением&lt;br /&gt;
*	Пересчет матрицы – по сути, скалярное произведение&lt;br /&gt;
*	Проверка условий останова – вычисление нормы&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
    float ** FuzzyCMeans (float** X, c, m, eps){&lt;br /&gt;
        n = X.size();&lt;br /&gt;
        r = X[0].size();&lt;br /&gt;
        centers = generateZeroFill(c, r)&lt;br /&gt;
        Wprev = genetateRandFill(n, c);&lt;br /&gt;
        W = Wprev;&lt;br /&gt;
        while (true){&lt;br /&gt;
            // обновляем центры кластеров &lt;br /&gt;
            for (int i=0; i&amp;lt;c; i++){&lt;br /&gt;
                float * num = new float []();&lt;br /&gt;
                float den = 0;&lt;br /&gt;
                for (int j=0; j&amp;lt;n; j++){&lt;br /&gt;
                    num += pow(W[j][i], m) * X[j];&lt;br /&gt;
                    den+=pow(W[j][i], m);&lt;br /&gt;
                }&lt;br /&gt;
                centers[i] = num / den;&lt;br /&gt;
            }&lt;br /&gt;
            //обновляем вероятности W и считаем расстояние между матрицами W и Wprev&lt;br /&gt;
            float max_diff = 0;&lt;br /&gt;
            for (int i=0; i&amp;lt;n; i++)&lt;br /&gt;
                for (int j=0; j&amp;lt;c; j++){&lt;br /&gt;
                    total = 0;&lt;br /&gt;
                    for (int m=0; m&amp;lt;с; m++)&lt;br /&gt;
                        total += pow(distance(X[i], centers[j]) / distance(X[i], centers[m]), 2/(m-1));&lt;br /&gt;
                    W[i][j] = 1/total;&lt;br /&gt;
                    max_diff = max(abs(Wprev[i][j]-W[i][j]), max_diff);&lt;br /&gt;
                    Wprev[i][j] = W[i][j];&lt;br /&gt;
               }               &lt;br /&gt;
           if (max_diff &amp;lt; eps):                &lt;br /&gt;
                break;&lt;br /&gt;
        }&lt;br /&gt;
        return W;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Последовательная сложность алгоритма состоит из сложности каждой итерации умноженной на их количество. Так как число итераций заранее неизвестно и зависит от входных параметров, рассмотрим сложность на каждой итерации. Наибольшую сложность представляет собой пересчет матрицы, сложность которого &amp;lt;math&amp;gt;O(c^2 nd)&amp;lt;/math&amp;gt; (по сравнению со сложностью &amp;lt;math&amp;gt;O(cnd)&amp;lt;/math&amp;gt; расчета расстояний, вычисления центроидов и проверки условия останова). Итого общая сложность алгоритма &amp;lt;math&amp;gt;O(c^2 ndi)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
Информационный граф представлен на рисунке ниже.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 1, 2, совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз для каждого кластера. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 1&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 2&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m*X_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем вектор размера &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; и матрицу размера &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;. &lt;br /&gt;
Далее совершаем поэлементное сложение векторов и матриц соответственно, а затем делим каждый столбец в матрице на соответствующий элемент в векторе.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй ярус&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 3, 4, 5 также совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 4&#039;&#039;&#039;: обновление значения &amp;lt;math&amp;gt;w_{ij}&amp;lt;/math&amp;gt; по указанной в разделе 1.2 в пункте 5 формуле.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 5&#039;&#039;&#039;: &amp;lt;math&amp;gt;maximum = max(|w_{ij} - w_{ij}^{prev}|, maximum)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 6&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^{prev} = w_{ij}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем число &amp;lt;math&amp;gt;maximum&amp;lt;/math&amp;gt;. Далее находим максимальное значение из полученных величин для каждой ветки. Затем проверяем условие останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:Scheme3.JPG]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельная сложность алгоритма: &amp;lt;math&amp;gt;M*c^2*i&amp;lt;/math&amp;gt;. Такая сложность получается за счет распараллеливания на каждом ярусе &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; операций. Иерархическая структура параллелизма подробно описана в [[#Информационный граф|п.1.7]].&lt;br /&gt;
&lt;br /&gt;
В алгоритме не возникает скошенного параллелизма.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Входные данные алгоритма: набор векторов &amp;lt;math&amp;gt;x_i&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i = 1,...,M&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
* Объем входных данных: &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt; , [количество наблюдений * размерность].&lt;br /&gt;
* Выходные данные алгоритма: матрица вероятностей принадлежности векторов кластерам &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Объем выходных данных: &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt; , [количество наблюдений * количество кластеров].&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной формы алгоритма: &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;&lt;br /&gt;
* Вычислительная мощность: &amp;lt;math&amp;gt;{dc^2i} \over {c+d}&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Устойчивость: алгоритм не является устойчивым, поэтому существует много исследований о том, как первоначально выбрать параметры кластеризации.&lt;br /&gt;
* Сбалансированность: в данном алгоритме операция умножения доминирует над операцией сложения. Операции между параллельными ветвями сбалансированны.&lt;br /&gt;
* Детерминированность: алгоритм не является детерминированным, так как матрица нечеткого разбиение генерируется произвольно.&lt;br /&gt;
* Степень исхода вершины информационного графа ( для одной интерации): 2 (3 - с учетом, если выходные данные пошли на следующую итерацию).&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма = &lt;br /&gt;
&lt;br /&gt;
==Особенности реализации последовательного алгоритма==&lt;br /&gt;
&lt;br /&gt;
==Локальность данных и вычислений==&lt;br /&gt;
&lt;br /&gt;
==Возможные способы и особенности параллельной реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
==Динамические характеристики и эффективность реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
==Выводы для классов архитектур==&lt;br /&gt;
&lt;br /&gt;
==Существующие реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
* Реализация алгоритма на POSTGRESQL: http://num-meth.srcc.msu.ru/zhurnal/tom_2012/pdf/v13r207.pdf&lt;br /&gt;
* Библиотека для MATLAB: http://www.mathworks.com/help/fuzzy/fcm.html (распространяется на коммерческой основе)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Gkhazeeva&amp;diff=15983</id>
		<title>Обсуждение участника:Gkhazeeva</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Gkhazeeva&amp;diff=15983"/>
		<updated>2016-11-06T16:47:56Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Статья [[Нечеткий алгоритм C средних]] =&lt;br /&gt;
* Не указан вклад каждого автора [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:54, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:55, 1 ноября 2016 (MSK)&lt;br /&gt;
* п. 1.2 номера формул следует выравнивать по правому краю, а не прилеплять вплотную к формуле [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:54, 25 октября 2016 (MSK)&lt;br /&gt;
** Условно исправлено. Форматирование сделано негодными средствами, но неясно, установлены ли средства (https://en.wikipedia.org/wiki/Help:Displaying_a_formula#Equation_numbering), чтобы сделать правильно [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:55, 1 ноября 2016 (MSK)&lt;br /&gt;
*** Пробовал сделать указанными Вами средствами - на этом ресурсе указанные Вами шаблоны не заработали [[Участник:Yushin|Павел Юшин]]&lt;br /&gt;
* п. 1.3 состоит из одного предложения и не дает достаточно информации [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:54, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:55, 1 ноября 2016 (MSK)&lt;br /&gt;
* п. 1.7 приведенный рисунок не является информационным графом: не все дуги ориентированы, имеются циклы [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:54, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:55, 1 ноября 2016 (MSK)&lt;br /&gt;
* п. 1.9 не приведено оценки объема входных и выходных данных [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:54, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:55, 1 ноября 2016 (MSK)&lt;br /&gt;
* в разделе 2 отсутствуют необходимые пункты, п. 2.2 должен быть 2.7 [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:54, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:55, 1 ноября 2016 (MSK)&lt;br /&gt;
* В списке литературы 1 ссылка - скопированный шаблон без реальной ссылки, 2 ссылка - просто URL без выходных данных источника [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:54, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено частично. Ссылка 2 по-прежнему не имеет достаточных выходных данных [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:55, 1 ноября 2016 (MSK)&lt;br /&gt;
*** На сайте, где студентам выдавалось задание ( http://parallel.ru/ss16 ), данный материал предоставлялся в списке источников (номер [8]) в таком же виде, как он указан в данной статье [[Участник:Yushin|Павел Юшин]]&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=14559</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=14559"/>
		<updated>2016-10-28T16:34:36Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(Mdc^2i)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - количество итераций&lt;br /&gt;
| input_data         = &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt;, [количество наблюдений * размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt;, [количество наблюдений * количество кластеров]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;2i&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]] ([[#Вычислительное ядро алгоритма|1.3]]; [[#Схема реализации последовательного алгоритма|1.5]]; [[#Последовательная сложность алгоритма|1.6]]; [[#Информационный граф|1.7]]; [[#Масштабируемость алгоритма и его реализации|2.4]]; [[#Существующие реализации алгоритма|2.7]]), [[Участник:Yushin|Павел Юшин]] ([[#Общее описание алгоритма|1.1]]; [[#Математическое описание алгоритма|1.2]]; [[#Макроструктура алгоритма|1.4]]; [[#Ресурс параллелизма алгоритма|1.8]]; [[#Входные и выходные данные алгоритма|1.9]]; [[#Свойства алгоритма|1.10]])&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;[http://www.tandfonline.com/doi/abs/10.1080/01969727308546046 | J. C. Dunn. A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters. Journal of Cybernetics, volume 3,1973 - Issue 3, pp 32-57]&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - экспоненциальный вес; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма будут отличать менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;[http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf | Нейский И.М. Классификация и сравнение методов кластеризации.]&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M&amp;lt;/math&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;0 &amp;lt; \sum_{i = 1}^M w_{ij} &amp;lt; M, j = 1, ..., c&amp;lt;/math&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда алгоритм принимает следующий вид:&lt;br /&gt;
&lt;br /&gt;
1) Задаем параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
2) Генерируем случайным образом матрицу нечеткого разбиения с учетом условий &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3) Рассчитываем центроиды (центры кластеров): &amp;lt;math&amp;gt;V_j = {{\sum_{i=1}^M w_{ij}^m * X_i} \over {\sum_{i=1}^M w_{ij}^m}}, j = 1, ..., c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Рассчитываем расстояния между объектами &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и центроидами:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_{ij} = {||X_i - V_j||}, i = 1,...,M; j = 1,...,c &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5) Пересчет элементов матрицы разбиения:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} &amp;gt;0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = {{1}\over {{ (\sum_{k=1}^c {{D_{ij}}\over{D_{ik}}} ) }^{2/(m-1)}}}, j = 1,...,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} =0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = \delta_{ij}, j = 1,...,c&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\delta_{ij}&amp;lt;/math&amp;gt; - символ Кронекера&lt;br /&gt;
&lt;br /&gt;
6) Если &amp;lt;math&amp;gt;|| F - F^{*} || &amp;lt; \varepsilon &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;F^{*}&amp;lt;/math&amp;gt; - матрица нечеткого разбиения предыдущей итерации, то идем далее, иначе возвращаемся на пункт 3.&lt;br /&gt;
&lt;br /&gt;
7) Конец.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром алгоритма являются следующие пункты:&lt;br /&gt;
&lt;br /&gt;
* Поиск &amp;lt;math&amp;gt;V_j&amp;lt;/math&amp;gt; - расчет центроидов (пункт 3 алгоритма)&lt;br /&gt;
* Нахождение &amp;lt;math&amp;gt;D_{ij}&amp;lt;/math&amp;gt; - расстояний между объектами (пункт 4 алгоритма)&lt;br /&gt;
* Пересчет &amp;lt;math&amp;gt;w_{ij}&amp;lt;/math&amp;gt; - элементов матрицы разбиения (пункт 5 алгоритма)&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Основные шаги при реализации алгоритма&lt;br /&gt;
*	Генерация случайной матрицы размера &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на где &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;, проверка условий&lt;br /&gt;
*	Расчет центроидов – по сути, скалярное произведение с нормировкой&lt;br /&gt;
*	Расчет расстояний – в общепринятом случае является скалярным произведением&lt;br /&gt;
*	Пересчет матрицы – по сути, скалярное произведение&lt;br /&gt;
*	Проверка условий останова – вычисление нормы&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
    float ** FuzzyCMeans (float** X, c, m, eps){&lt;br /&gt;
        n = X.size();&lt;br /&gt;
        r = X[0].size();&lt;br /&gt;
        centers = generateZeroFill(c, r)&lt;br /&gt;
        Wprev = genetateRandFill(n, c);&lt;br /&gt;
        W = Wprev;&lt;br /&gt;
        while (true){&lt;br /&gt;
            // обновляем центры кластеров &lt;br /&gt;
            for (int i=0; i&amp;lt;c; i++){&lt;br /&gt;
                float * num = new float []();&lt;br /&gt;
                float den = 0;&lt;br /&gt;
                for (int j=0; j&amp;lt;n; j++){&lt;br /&gt;
                    num += pow(W[j][i], m) * X[j];&lt;br /&gt;
                    den+=pow(W[j][i], m);&lt;br /&gt;
                }&lt;br /&gt;
                centers[i] = num / den;&lt;br /&gt;
            }&lt;br /&gt;
            //обновляем вероятности W и считаем расстояние между матрицами W и Wprev&lt;br /&gt;
            float max_diff = 0;&lt;br /&gt;
            for (int i=0; i&amp;lt;n; i++)&lt;br /&gt;
                for (int j=0; j&amp;lt;c; j++){&lt;br /&gt;
                    total = 0;&lt;br /&gt;
                    for (int m=0; m&amp;lt;с; m++)&lt;br /&gt;
                        total += pow(distance(X[i], centers[j]) / distance(X[i], centers[m]), 2/(m-1));&lt;br /&gt;
                    W[i][j] = 1/total;&lt;br /&gt;
                    max_diff = max(abs(Wprev[i][j]-W[i][j]), max_diff);&lt;br /&gt;
                    Wprev[i][j] = W[i][j];&lt;br /&gt;
               }               &lt;br /&gt;
           if (max_diff &amp;lt; eps):                &lt;br /&gt;
                break;&lt;br /&gt;
        }&lt;br /&gt;
        return W;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Последовательная сложность алгоритма состоит из сложности каждой итерации умноженной на их количество. Так как число итераций заранее неизвестно и зависит от входных параметров, рассмотрим сложность на каждой итерации. Наибольшую сложность представляет собой пересчет матрицы, сложность которого &amp;lt;math&amp;gt;O(c^2 nd)&amp;lt;/math&amp;gt; (по сравнению со сложностью &amp;lt;math&amp;gt;O(cnd)&amp;lt;/math&amp;gt; расчета расстояний, вычисления центроидов и проверки условия останова). Итого общая сложность алгоритма &amp;lt;math&amp;gt;O(c^2 ndi)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
Информационный граф представлен на рисунке ниже.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 1, 2, совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз для каждого кластера. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 1&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 2&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m*X_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем вектор размера &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; и матрицу размера &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;. &lt;br /&gt;
Далее совершаем поэлементное сложение векторов и матриц соответственно, а затем делим каждый столбец в матрице на соответствующий элемент в векторе.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй ярус&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 3, 4, 5 также совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 4&#039;&#039;&#039;: обновление значения &amp;lt;math&amp;gt;w_{ij}&amp;lt;/math&amp;gt; по указанной в разделе 1.2 в пункте 5 формуле.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 5&#039;&#039;&#039;: &amp;lt;math&amp;gt;maximum = max(|w_{ij} - w_{ij}^{prev}|, maximum)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 6&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^{prev} = w_{ij}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем число &amp;lt;math&amp;gt;maximum&amp;lt;/math&amp;gt;. Далее находим максимальное значение из полученных величин для каждой ветки. Затем проверяем условие останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:Scheme.JPG]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельная сложность алгоритма: &amp;lt;math&amp;gt;M*c^2*i&amp;lt;/math&amp;gt;. Такая сложность получается за счет распараллеливания на каждом ярусе &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; операций. Иерархическая структура параллелизма подробно описана в [[#Информационный граф|п.1.7]].&lt;br /&gt;
&lt;br /&gt;
В алгоритме не возникает скошенного параллелизма.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Входные данные алгоритма: набор векторов &amp;lt;math&amp;gt;x_i&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i = 1,...,M&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
* Объем входных данных: &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt; , [количество наблюдений * размерность].&lt;br /&gt;
* Выходные данные алгоритма: матрица вероятностей принадлежности векторов кластерам &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Объем выходных данных: &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt; , [количество наблюдений * количество кластеров].&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной формы алгоритма: &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;&lt;br /&gt;
* Вычислительная мощность: &amp;lt;math&amp;gt;{dc^2i} \over {c+d}&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Устойчивость: алгоритм не является устойчивым, поэтому существует много исследований о том, как первоначально выбрать параметры кластеризации.&lt;br /&gt;
* Сбалансированность: в данном алгоритме операция умножения доминирует над операцией сложения. Операции между параллельными ветвями сбалансированны.&lt;br /&gt;
* Детерминированность: алгоритм не является детерминированным, так как матрица нечеткого разбиение генерируется произвольно.&lt;br /&gt;
* Степень исхода вершины информационного графа ( для одной интерации): 2 (3 - с учетом, если выходные данные пошли на следующую итерацию).&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма = &lt;br /&gt;
&lt;br /&gt;
==Особенности реализации последовательного алгоритма==&lt;br /&gt;
&lt;br /&gt;
==Локальность данных и вычислений==&lt;br /&gt;
&lt;br /&gt;
==Возможные способы и особенности параллельной реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
==Динамические характеристики и эффективность реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
==Выводы для классов архитектур==&lt;br /&gt;
&lt;br /&gt;
==Существующие реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
* Реализация алгоритма на POSTGRESQL: http://num-meth.srcc.msu.ru/zhurnal/tom_2012/pdf/v13r207.pdf&lt;br /&gt;
* Библиотека для MATLAB: http://www.mathworks.com/help/fuzzy/fcm.html (распространяется на коммерческой основе)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=14558</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=14558"/>
		<updated>2016-10-28T16:27:42Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(Mdc^2i)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - количество итераций&lt;br /&gt;
| input_data         = &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt;, [количество наблюдений * размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt;, [количество наблюдений * количество кластеров]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;2i&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]] ([[#Вычислительное ядро алгоритма|1.3]]; [[#Схема реализации последовательного алгоритма|1.5]]; [[#Последовательная сложность алгоритма|1.6]]; [[#Информационный граф|1.7]]; [[#Масштабируемость алгоритма и его реализации|2.4]]; [[#Существующие реализации алгоритма|2.7]]), [[Участник:Yushin|Павел Юшин]] ([[#Общее описание алгоритма|1.1]]; [[#Математическое описание алгоритма|1.2]]; [[#Макроструктура алгоритма|1.4]]; [[#Ресурс параллелизма алгоритма|1.8]]; [[#Входные и выходные данные алгоритма|1.9]]; [[#Свойства алгоритма|1.10]])&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;[http://www.tandfonline.com/doi/abs/10.1080/01969727308546046 | J. C. Dunn. A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters. Journal of Cybernetics, volume 3,1973 - Issue 3, pp 32-57]&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - экспоненциальный вес; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма будут отличать менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;[http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf | Нейский И.М. Классификация и сравнение методов кластеризации.]&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M&amp;lt;/math&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;0 &amp;lt; \sum_{i = 1}^M w_{ij} &amp;lt; M, j = 1, ..., c&amp;lt;/math&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда алгоритм принимает следующий вид:&lt;br /&gt;
&lt;br /&gt;
1) Задаем параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
2) Генерируем случайным образом матрицу нечеткого разбиения с учетом условий &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3) Рассчитываем центроиды (центры кластеров): &amp;lt;math&amp;gt;V_j = {{\sum_{i=1}^M w_{ij}^m * X_i} \over {\sum_{i=1}^M w_{ij}^m}}, j = 1, ..., c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Рассчитываем расстояния между объектами &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и центроидами:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_{ij} = {||X_i - V_j||}, i = 1,...,M; j = 1,...,c &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5) Пересчет элементов матрицы разбиения:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} &amp;gt;0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = {{1}\over {{ (\sum_{k=1}^c {{D_{ij}}\over{D_{ik}}} ) }^{2/(m-1)}}}, j = 1,...,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} =0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = \delta_{ij}, j = 1,...,c&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\delta_{ij}&amp;lt;/math&amp;gt; - символ Кронекера&lt;br /&gt;
&lt;br /&gt;
6) Если &amp;lt;math&amp;gt;|| F - F^{*} || &amp;lt; \varepsilon &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;F^{*}&amp;lt;/math&amp;gt; - матрица нечеткого разбиения предыдущей итерации, то идем далее, иначе возвращаемся на пункт 3.&lt;br /&gt;
&lt;br /&gt;
7) Конец.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром алгоритма являются пункты (3), (4), (5) - расчет центроидов, вычисление расстояний и пересчет элементов матрицы соответственно&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Основные шаги при реализации алгоритма&lt;br /&gt;
*	Генерация случайной матрицы размера &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на где &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;, проверка условий&lt;br /&gt;
*	Расчет центроидов – по сути, скалярное произведение с нормировкой&lt;br /&gt;
*	Расчет расстояний – в общепринятом случае является скалярным произведением&lt;br /&gt;
*	Пересчет матрицы – по сути, скалярное произведение&lt;br /&gt;
*	Проверка условий останова – вычисление нормы&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
    float ** FuzzyCMeans (float** X, c, m, eps){&lt;br /&gt;
        n = X.size();&lt;br /&gt;
        r = X[0].size();&lt;br /&gt;
        centers = generateZeroFill(c, r)&lt;br /&gt;
        Wprev = genetateRandFill(n, c);&lt;br /&gt;
        W = Wprev;&lt;br /&gt;
        while (true){&lt;br /&gt;
            // обновляем центры кластеров &lt;br /&gt;
            for (int i=0; i&amp;lt;c; i++){&lt;br /&gt;
                float * num = new float []();&lt;br /&gt;
                float den = 0;&lt;br /&gt;
                for (int j=0; j&amp;lt;n; j++){&lt;br /&gt;
                    num += pow(W[j][i], m) * X[j];&lt;br /&gt;
                    den+=pow(W[j][i], m);&lt;br /&gt;
                }&lt;br /&gt;
                centers[i] = num / den;&lt;br /&gt;
            }&lt;br /&gt;
            //обновляем вероятности W и считаем расстояние между матрицами W и Wprev&lt;br /&gt;
            float max_diff = 0;&lt;br /&gt;
            for (int i=0; i&amp;lt;n; i++)&lt;br /&gt;
                for (int j=0; j&amp;lt;c; j++){&lt;br /&gt;
                    total = 0;&lt;br /&gt;
                    for (int m=0; m&amp;lt;с; m++)&lt;br /&gt;
                        total += pow(distance(X[i], centers[j]) / distance(X[i], centers[m]), 2/(m-1));&lt;br /&gt;
                    W[i][j] = 1/total;&lt;br /&gt;
                    max_diff = max(abs(Wprev[i][j]-W[i][j]), max_diff);&lt;br /&gt;
                    Wprev[i][j] = W[i][j];&lt;br /&gt;
               }               &lt;br /&gt;
           if (max_diff &amp;lt; eps):                &lt;br /&gt;
                break;&lt;br /&gt;
        }&lt;br /&gt;
        return W;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Последовательная сложность алгоритма состоит из сложности каждой итерации умноженной на их количество. Так как число итераций заранее неизвестно и зависит от входных параметров, рассмотрим сложность на каждой итерации. Наибольшую сложность представляет собой пересчет матрицы, сложность которого &amp;lt;math&amp;gt;O(c^2 nd)&amp;lt;/math&amp;gt; (по сравнению со сложностью &amp;lt;math&amp;gt;O(cnd)&amp;lt;/math&amp;gt; расчета расстояний, вычисления центроидов и проверки условия останова). Итого общая сложность алгоритма &amp;lt;math&amp;gt;O(c^2 ndi)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
Информационный граф представлен на рисунке ниже.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 1, 2, совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз для каждого кластера. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 1&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 2&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m*X_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем вектор размера &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; и матрицу размера &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;. &lt;br /&gt;
Далее совершаем поэлементное сложение векторов и матриц соответственно, а затем делим каждый столбец в матрице на соответствующий элемент в векторе.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй ярус&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 3, 4, 5 также совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 4&#039;&#039;&#039;: обновление значения &amp;lt;math&amp;gt;w_{ij}&amp;lt;/math&amp;gt; по указанной в разделе 1.2 в пункте 5 формуле.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 5&#039;&#039;&#039;: &amp;lt;math&amp;gt;maximum = max(|w_{ij} - w_{ij}^{prev}|, maximum)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 6&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^{prev} = w_{ij}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем число &amp;lt;math&amp;gt;maximum&amp;lt;/math&amp;gt;. Далее находим максимальное значение из полученных величин для каждой ветки. Затем проверяем условие останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:Scheme.JPG]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельная сложность алгоритма: &amp;lt;math&amp;gt;M*c^2*i&amp;lt;/math&amp;gt;. Такая сложность получается за счет распараллеливания на каждом ярусе &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; операций. Иерархическая структура параллелизма подробно описана в [[#Информационный граф|п.1.7]].&lt;br /&gt;
&lt;br /&gt;
В алгоритме не возникает скошенного параллелизма.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Входные данные алгоритма: набор векторов &amp;lt;math&amp;gt;x_i&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i = 1,...,M&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
* Объем входных данных: &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt; , [количество наблюдений * размерность].&lt;br /&gt;
* Выходные данные алгоритма: матрица вероятностей принадлежности векторов кластерам &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Объем выходных данных: &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt; , [количество наблюдений * количество кластеров].&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной формы алгоритма: &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;&lt;br /&gt;
* Вычислительная мощность: &amp;lt;math&amp;gt;{dc^2i} \over {c+d}&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Устойчивость: алгоритм не является устойчивым, поэтому существует много исследований о том, как первоначально выбрать параметры кластеризации.&lt;br /&gt;
* Сбалансированность: в данном алгоритме операция умножения доминирует над операцией сложения. Операции между параллельными ветвями сбалансированны.&lt;br /&gt;
* Детерминированность: алгоритм не является детерминированным, так как матрица нечеткого разбиение генерируется произвольно.&lt;br /&gt;
* Степень исхода вершины информационного графа ( для одной интерации): 2 (3 - с учетом, если выходные данные пошли на следующую итерацию).&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма = &lt;br /&gt;
&lt;br /&gt;
==Особенности реализации последовательного алгоритма==&lt;br /&gt;
&lt;br /&gt;
==Локальность данных и вычислений==&lt;br /&gt;
&lt;br /&gt;
==Возможные способы и особенности параллельной реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
==Динамические характеристики и эффективность реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
==Выводы для классов архитектур==&lt;br /&gt;
&lt;br /&gt;
==Существующие реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
* Реализация алгоритма на POSTGRESQL: http://num-meth.srcc.msu.ru/zhurnal/tom_2012/pdf/v13r207.pdf&lt;br /&gt;
* Библиотека для MATLAB: http://www.mathworks.com/help/fuzzy/fcm.html (распространяется на коммерческой основе)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=14557</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=14557"/>
		<updated>2016-10-28T16:27:15Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(Mdc^2i)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - количество итераций&lt;br /&gt;
| input_data         = &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt;, [количество наблюдений * размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt;, [количество наблюдений * количество кластеров]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;2i&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]] ([[#Вычислительное ядро алгоритма|1.3]]; [[#Схема реализации последовательного алгоритма|1.5]]; [[#Последовательная сложность алгоритма|1.6]]; [[#Информационный граф|1.7]]; [[#Масштабируемость алгоритма и его реализации|2.4]]; [[#Существующие реализации алгоритма|2.7]]), [[Участник:Yushin|Павел Юшин]] ([[#Общее описание алгоритма|1.1]]; [[#Математическое описание алгоритма|1.2]]; [[#Макроструктура алгоритма|1.4]]; [[#Ресурс параллелизма алгоритма|1.8]]; [[#Входные и выходные данные алгоритма|1.9]]; [[#Свойства алгоритма|1.10]])&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;[http://www.tandfonline.com/doi/abs/10.1080/01969727308546046 | J. C. Dunn. A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters. Journal of Cybernetics, volume 3,1973 - Issue 3, pp 32-57]&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - экспоненциальный вес; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма будут отличать менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;[http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf | Нейский И.М. Классификация и сравнение методов кластеризации.]&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M&amp;lt;/math&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;0 &amp;lt; \sum_{i = 1}^M w_{ij} &amp;lt; M, j = 1, ..., c&amp;lt;/math&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда алгоритм принимает следующий вид:&lt;br /&gt;
&lt;br /&gt;
1) Задаем параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
2) Генерируем случайным образом матрицу нечеткого разбиения с учетом условий &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3) Рассчитываем центроиды (центры кластеров): &amp;lt;math&amp;gt;V_j = {{\sum_{i=1}^M w_{ij}^m * X_i} \over {\sum_{i=1}^M w_{ij}^m}}, j = 1, ..., c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Рассчитываем расстояния между объектами &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и центроидами:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_{ij} = {||X_i - V_j||}, i = 1,...,M; j = 1,...,c &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5) Пересчет элементов матрицы разбиения:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} &amp;gt;0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = {{1}\over {{ (\sum_{k=1}^c {{D_{ij}}\over{D_{ik}}} ) }^{2/(m-1)}}}, j = 1,...,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} =0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = \delta_{ij}, j = 1,...,c&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\delta_{ij}&amp;lt;/math&amp;gt; - символ Кронекера&lt;br /&gt;
&lt;br /&gt;
6) Если &amp;lt;math&amp;gt;|| F - F^{*} || &amp;lt; \varepsilon &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;F^{*}&amp;lt;/math&amp;gt; - матрица нечеткого разбиения предыдущей итерации, то идем далее, иначе возвращаемся на пункт 3.&lt;br /&gt;
&lt;br /&gt;
7) Конец.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром алгоритма являются пункты (3), (4), (5) - расчет центроидов, вычисление расстояний и пересчет элементов матрицы соответственно&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Основные шаги при реализации алгоритма&lt;br /&gt;
*	Генерация случайной матрицы размера &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на где &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;, проверка условий&lt;br /&gt;
*	Расчет центроидов – по сути, скалярное произведение с нормировкой&lt;br /&gt;
*	Расчет расстояний – в общепринятом случае является скалярным произведением&lt;br /&gt;
*	Пересчет матрицы – по сути, скалярное произведение&lt;br /&gt;
*	Проверка условий останова – вычисление нормы&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
    float ** FuzzyCMeans (float** X, c, m, eps){&lt;br /&gt;
        n = X.size();&lt;br /&gt;
        r = X[0].size();&lt;br /&gt;
        centers = generateZeroFill(c, r)&lt;br /&gt;
        Wprev = genetateRandFill(n, c);&lt;br /&gt;
        W = Wprev;&lt;br /&gt;
        while (true){&lt;br /&gt;
            // обновляем центры кластеров &lt;br /&gt;
            for (int i=0; i&amp;lt;c; i++){&lt;br /&gt;
                float * num = new float []();&lt;br /&gt;
                float den = 0;&lt;br /&gt;
                for (int j=0; j&amp;lt;n; j++){&lt;br /&gt;
                    num += pow(W[j][i], m) * X[j];&lt;br /&gt;
                    den+=pow(W[j][i], m);&lt;br /&gt;
                }&lt;br /&gt;
                centers[i] = num / den;&lt;br /&gt;
            }&lt;br /&gt;
            //обновляем вероятности W и считаем расстояние между матрицами W и Wprev&lt;br /&gt;
            float max_diff = 0;&lt;br /&gt;
            for (int i=0; i&amp;lt;n; i++)&lt;br /&gt;
                for (int j=0; j&amp;lt;c; j++){&lt;br /&gt;
                    total = 0;&lt;br /&gt;
                    for (int m=0; m&amp;lt;с; m++)&lt;br /&gt;
                        total += pow(distance(X[i], centers[j]) / distance(X[i], centers[m]), 2/(m-1));&lt;br /&gt;
                    W[i][j] = 1/total;&lt;br /&gt;
                    max_diff = max(abs(Wprev[i][j]-W[i][j]), max_diff);&lt;br /&gt;
                    Wprev[i][j] = W[i][j];&lt;br /&gt;
               }               &lt;br /&gt;
           if (max_diff &amp;lt; eps):                &lt;br /&gt;
                break;&lt;br /&gt;
        }&lt;br /&gt;
        return W;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Последовательная сложность алгоритма состоит из сложности каждой итерации умноженной на их количество. Так как число итераций заранее неизвестно и зависит от входных параметров, рассмотрим сложность на каждой итерации. Наибольшую сложность представляет собой пересчет матрицы, сложность которого &amp;lt;math&amp;gt;O(c^2 nd)&amp;lt;/math&amp;gt; (по сравнению со сложностью &amp;lt;math&amp;gt;O(cnd)&amp;lt;/math&amp;gt; расчета расстояний, вычисления центроидов и проверки условия останова). Итого общая сложность алгоритма &amp;lt;math&amp;gt;O(c^2 ndi)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
Информационный граф представлен на рисунке ниже.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 1, 2, совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз для каждого кластера. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 1&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 2&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m*X_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем вектор размера &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; и матрицу размера &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;. &lt;br /&gt;
Далее совершаем поэлементное сложение векторов и матриц соответственно, а затем делим каждый столбец в матрице на соответствующий элемент в векторе.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй ярус&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 3, 4, 5 также совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 4&#039;&#039;&#039;: обновление значения &amp;lt;math&amp;gt;w_{ij}&amp;lt;/math&amp;gt; по указанной в разделе 1.2 в пункте 5 формуле.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 5&#039;&#039;&#039;: &amp;lt;math&amp;gt;maximum = max(|w_{ij} - w_{ij}^{prev}|, maximum)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 6&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^{prev} = w_{ij}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем число &amp;lt;math&amp;gt;maximum&amp;lt;/math&amp;gt;. Далее находим максимальное значение из полученных величин для каждой ветки. Затем проверяем условие останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:Scheme.JPG]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельная сложность алгоритма: &amp;lt;math&amp;gt;M*c^2*i&amp;lt;/math&amp;gt;. Такая сложность получается за счет распараллеливания на каждом ярусе &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; операций. Иерархическая структура параллелизма подробно описана в [[#Информационный граф|п.1.7]].&lt;br /&gt;
&lt;br /&gt;
В алгоритме не возникает скошенного параллелизма.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Входные данные алгоритма: набор векторов &amp;lt;math&amp;gt;x_i&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i = 1,...,M&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
* Объем входных данных: &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt;, [количество наблюдений * размерность].&lt;br /&gt;
* Выходные данные алгоритма: матрица вероятностей принадлежности векторов кластерам &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Объем выходных данных: &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt;, [количество наблюдений * количество кластеров].&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной формы алгоритма: &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;&lt;br /&gt;
* Вычислительная мощность: &amp;lt;math&amp;gt;{dc^2i} \over {c+d}&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Устойчивость: алгоритм не является устойчивым, поэтому существует много исследований о том, как первоначально выбрать параметры кластеризации.&lt;br /&gt;
* Сбалансированность: в данном алгоритме операция умножения доминирует над операцией сложения. Операции между параллельными ветвями сбалансированны.&lt;br /&gt;
* Детерминированность: алгоритм не является детерминированным, так как матрица нечеткого разбиение генерируется произвольно.&lt;br /&gt;
* Степень исхода вершины информационного графа ( для одной интерации): 2 (3 - с учетом, если выходные данные пошли на следующую итерацию).&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма = &lt;br /&gt;
&lt;br /&gt;
==Особенности реализации последовательного алгоритма==&lt;br /&gt;
&lt;br /&gt;
==Локальность данных и вычислений==&lt;br /&gt;
&lt;br /&gt;
==Возможные способы и особенности параллельной реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
==Динамические характеристики и эффективность реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
==Выводы для классов архитектур==&lt;br /&gt;
&lt;br /&gt;
==Существующие реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
* Реализация алгоритма на POSTGRESQL: http://num-meth.srcc.msu.ru/zhurnal/tom_2012/pdf/v13r207.pdf&lt;br /&gt;
* Библиотека для MATLAB: http://www.mathworks.com/help/fuzzy/fcm.html (распространяется на коммерческой основе)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=14556</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=14556"/>
		<updated>2016-10-28T16:25:20Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(Mdc^2i)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - количество итераций&lt;br /&gt;
| input_data         = &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt;, [количество наблюдений * размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt;, [количество наблюдений * количество кластеров]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;2i&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]] ([[#Вычислительное ядро алгоритма|1.3]]; [[#Схема реализации последовательного алгоритма|1.5]]; [[#Последовательная сложность алгоритма|1.6]]; [[#Информационный граф|1.7]]; [[#Масштабируемость алгоритма и его реализации|2.4]]; [[#Существующие реализации алгоритма|2.7]]), [[Участник:Yushin|Павел Юшин]] ([[#Общее описание алгоритма|1.1]]; [[#Математическое описание алгоритма|1.2]]; [[#Макроструктура алгоритма|1.4]]; [[#Ресурс параллелизма алгоритма|1.8]]; [[#Входные и выходные данные алгоритма|1.9]]; [[#Свойства алгоритма|1.10]])&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;[http://www.tandfonline.com/doi/abs/10.1080/01969727308546046 | J. C. Dunn. A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters. Journal of Cybernetics, volume 3,1973 - Issue 3, pp 32-57]&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - экспоненциальный вес; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма будут отличать менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;[http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf | Нейский И.М. Классификация и сравнение методов кластеризации.]&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M&amp;lt;/math&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;0 &amp;lt; \sum_{i = 1}^M w_{ij} &amp;lt; M, j = 1, ..., c&amp;lt;/math&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда алгоритм принимает следующий вид:&lt;br /&gt;
&lt;br /&gt;
1) Задаем параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
2) Генерируем случайным образом матрицу нечеткого разбиения с учетом условий &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3) Рассчитываем центроиды (центры кластеров): &amp;lt;math&amp;gt;V_j = {{\sum_{i=1}^M w_{ij}^m * X_i} \over {\sum_{i=1}^M w_{ij}^m}}, j = 1, ..., c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Рассчитываем расстояния между объектами &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и центроидами:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_{ij} = {||X_i - V_j||}, i = 1,...,M; j = 1,...,c &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5) Пересчет элементов матрицы разбиения:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} &amp;gt;0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = {{1}\over {{ (\sum_{k=1}^c {{D_{ij}}\over{D_{ik}}} ) }^{2/(m-1)}}}, j = 1,...,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} =0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = \delta_{ij}, j = 1,...,c&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\delta_{ij}&amp;lt;/math&amp;gt; - символ Кронекера&lt;br /&gt;
&lt;br /&gt;
6) Если &amp;lt;math&amp;gt;|| F - F^{*} || &amp;lt; \varepsilon &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;F^{*}&amp;lt;/math&amp;gt; - матрица нечеткого разбиения предыдущей итерации, то идем далее, иначе возвращаемся на пункт 3.&lt;br /&gt;
&lt;br /&gt;
7) Конец.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром алгоритма являются пункты (3), (4), (5) - расчет центроидов, вычисление расстояний и пересчет элементов матрицы соответственно&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Основные шаги при реализации алгоритма&lt;br /&gt;
*	Генерация случайной матрицы размера &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на где &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;, проверка условий&lt;br /&gt;
*	Расчет центроидов – по сути, скалярное произведение с нормировкой&lt;br /&gt;
*	Расчет расстояний – в общепринятом случае является скалярным произведением&lt;br /&gt;
*	Пересчет матрицы – по сути, скалярное произведение&lt;br /&gt;
*	Проверка условий останова – вычисление нормы&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
    float ** FuzzyCMeans (float** X, c, m, eps){&lt;br /&gt;
        n = X.size();&lt;br /&gt;
        r = X[0].size();&lt;br /&gt;
        centers = generateZeroFill(c, r)&lt;br /&gt;
        Wprev = genetateRandFill(n, c);&lt;br /&gt;
        W = Wprev;&lt;br /&gt;
        while (true){&lt;br /&gt;
            // обновляем центры кластеров &lt;br /&gt;
            for (int i=0; i&amp;lt;c; i++){&lt;br /&gt;
                float * num = new float []();&lt;br /&gt;
                float den = 0;&lt;br /&gt;
                for (int j=0; j&amp;lt;n; j++){&lt;br /&gt;
                    num += pow(W[j][i], m) * X[j];&lt;br /&gt;
                    den+=pow(W[j][i], m);&lt;br /&gt;
                }&lt;br /&gt;
                centers[i] = num / den;&lt;br /&gt;
            }&lt;br /&gt;
            //обновляем вероятности W и считаем расстояние между матрицами W и Wprev&lt;br /&gt;
            float max_diff = 0;&lt;br /&gt;
            for (int i=0; i&amp;lt;n; i++)&lt;br /&gt;
                for (int j=0; j&amp;lt;c; j++){&lt;br /&gt;
                    total = 0;&lt;br /&gt;
                    for (int m=0; m&amp;lt;с; m++)&lt;br /&gt;
                        total += pow(distance(X[i], centers[j]) / distance(X[i], centers[m]), 2/(m-1));&lt;br /&gt;
                    W[i][j] = 1/total;&lt;br /&gt;
                    max_diff = max(abs(Wprev[i][j]-W[i][j]), max_diff);&lt;br /&gt;
                    Wprev[i][j] = W[i][j];&lt;br /&gt;
               }               &lt;br /&gt;
           if (max_diff &amp;lt; eps):                &lt;br /&gt;
                break;&lt;br /&gt;
        }&lt;br /&gt;
        return W;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Последовательная сложность алгоритма состоит из сложности каждой итерации умноженной на их количество. Так как число итераций заранее неизвестно и зависит от входных параметров, рассмотрим сложность на каждой итерации. Наибольшую сложность представляет собой пересчет матрицы, сложность которого &amp;lt;math&amp;gt;O(c^2 nd)&amp;lt;/math&amp;gt; (по сравнению со сложностью &amp;lt;math&amp;gt;O(cnd)&amp;lt;/math&amp;gt; расчета расстояний, вычисления центроидов и проверки условия останова). Итого общая сложность алгоритма &amp;lt;math&amp;gt;O(c^2 ndi)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
Информационный граф представлен на рисунке ниже.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 1, 2, совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз для каждого кластера. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 1&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 2&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m*X_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем вектор размера &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; и матрицу размера &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;. &lt;br /&gt;
Далее совершаем поэлементное сложение векторов и матриц соответственно, а затем делим каждый столбец в матрице на соответствующий элемент в векторе.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй ярус&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 3, 4, 5 также совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 4&#039;&#039;&#039;: обновление значения &amp;lt;math&amp;gt;w_{ij}&amp;lt;/math&amp;gt; по указанной в разделе 1.2 в пункте 5 формуле.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 5&#039;&#039;&#039;: &amp;lt;math&amp;gt;maximum = max(|w_{ij} - w_{ij}^{prev}|, maximum)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 6&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^{prev} = w_{ij}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем число &amp;lt;math&amp;gt;maximum&amp;lt;/math&amp;gt;. Далее находим максимальное значение из полученных величин для каждой ветки. Затем проверяем условие останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:Scheme.JPG]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельная сложность алгоритма: &amp;lt;math&amp;gt;M*c^2*i&amp;lt;/math&amp;gt;. Такая сложность получается за счет распараллеливания на каждом ярусе &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; операций. Иерархическая структура параллелизма подробно описана в [[#Информационный граф|п.1.7]].&lt;br /&gt;
&lt;br /&gt;
В алгоритме не возникает скошенного параллелизма.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Входные данные алгоритма: набор векторов &amp;lt;math&amp;gt;x_i&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i = 1,...,M&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
* Выходные данные алгоритма: матрица вероятностей принадлежности векторов кластерам &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной формы алгоритма: &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;&lt;br /&gt;
* Вычислительная мощность: &amp;lt;math&amp;gt;{dc^2i} \over {c+d}&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Устойчивость: алгоритм не является устойчивым, поэтому существует много исследований о том, как первоначально выбрать параметры кластеризации.&lt;br /&gt;
* Сбалансированность: в данном алгоритме операция умножения доминирует над операцией сложения. Операции между параллельными ветвями сбалансированны.&lt;br /&gt;
* Детерминированность: алгоритм не является детерминированным, так как матрица нечеткого разбиение генерируется произвольно.&lt;br /&gt;
* Степень исхода вершины информационного графа ( для одной интерации): 2 (3 - с учетом, если выходные данные пошли на следующую итерацию).&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма = &lt;br /&gt;
&lt;br /&gt;
==Особенности реализации последовательного алгоритма==&lt;br /&gt;
&lt;br /&gt;
==Локальность данных и вычислений==&lt;br /&gt;
&lt;br /&gt;
==Возможные способы и особенности параллельной реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
==Динамические характеристики и эффективность реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
==Выводы для классов архитектур==&lt;br /&gt;
&lt;br /&gt;
==Существующие реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
* Реализация алгоритма на POSTGRESQL: http://num-meth.srcc.msu.ru/zhurnal/tom_2012/pdf/v13r207.pdf&lt;br /&gt;
* Библиотека для MATLAB: http://www.mathworks.com/help/fuzzy/fcm.html (распространяется на коммерческой основе)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=14555</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=14555"/>
		<updated>2016-10-28T16:13:48Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(Mdc^2i)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - количество итераций&lt;br /&gt;
| input_data         = &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt;, [количество наблюдений * размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt;, [количество наблюдений * количество кластеров]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;2i&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]] ([[#Вычислительное ядро алгоритма|1.3]]; [[#Схема реализации последовательного алгоритма|1.5]]; [[#Последовательная сложность алгоритма|1.6]]; [[#Информационный граф|1.7]]; [[#Масштабируемость алгоритма и его реализации|2.4]]; [[#Существующие реализации алгоритма|2.7]]), [[Участник:Yushin|Павел Юшин]] ([[#Общее описание алгоритма|1.1]]; [[#Математическое описание алгоритма|1.2]]; [[#Макроструктура алгоритма|1.4]]; [[#Ресурс параллелизма алгоритма|1.8]]; [[#Входные и выходные данные алгоритма|1.9]]; [[#Свойства алгоритма|1.10]])&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;{{Cite journal|last=Dunn|first=J. C.|date=1973-01-01|title=A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters|url=http://dx.doi.org/10.1080/01969727308546046|journal=Journal of Cybernetics|volume=3|issue=3|pages=32–57|doi=10.1080/01969727308546046|issn=0022-0280}}&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - экспоненциальный вес; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма будут отличать менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M&amp;lt;/math&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;0 &amp;lt; \sum_{i = 1}^M w_{ij} &amp;lt; M, j = 1, ..., c&amp;lt;/math&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда алгоритм принимает следующий вид:&lt;br /&gt;
&lt;br /&gt;
1) Задаем параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
2) Генерируем случайным образом матрицу нечеткого разбиения с учетом условий &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3) Рассчитываем центроиды (центры кластеров): &amp;lt;math&amp;gt;V_j = {{\sum_{i=1}^M w_{ij}^m * X_i} \over {\sum_{i=1}^M w_{ij}^m}}, j = 1, ..., c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Рассчитываем расстояния между объектами &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и центроидами:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_{ij} = {||X_i - V_j||}, i = 1,...,M; j = 1,...,c &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5) Пересчет элементов матрицы разбиения:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} &amp;gt;0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = {{1}\over {{ (\sum_{k=1}^c {{D_{ij}}\over{D_{ik}}} ) }^{2/(m-1)}}}, j = 1,...,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} =0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = \delta_{ij}, j = 1,...,c&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\delta_{ij}&amp;lt;/math&amp;gt; - символ Кронекера&lt;br /&gt;
&lt;br /&gt;
6) Если &amp;lt;math&amp;gt;|| F - F^{*} || &amp;lt; \varepsilon &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;F^{*}&amp;lt;/math&amp;gt; - матрица нечеткого разбиения предыдущей итерации, то идем далее, иначе возвращаемся на пункт 3.&lt;br /&gt;
&lt;br /&gt;
7) Конец.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром алгоритма являются пункты (3), (4), (5) - расчет центроидов, вычисление расстояний и пересчет элементов матрицы соответственно&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Основные шаги при реализации алгоритма&lt;br /&gt;
*	Генерация случайной матрицы размера &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на где &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;, проверка условий&lt;br /&gt;
*	Расчет центроидов – по сути, скалярное произведение с нормировкой&lt;br /&gt;
*	Расчет расстояний – в общепринятом случае является скалярным произведением&lt;br /&gt;
*	Пересчет матрицы – по сути, скалярное произведение&lt;br /&gt;
*	Проверка условий останова – вычисление нормы&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
    float ** FuzzyCMeans (float** X, c, m, eps){&lt;br /&gt;
        n = X.size();&lt;br /&gt;
        r = X[0].size();&lt;br /&gt;
        centers = generateZeroFill(c, r)&lt;br /&gt;
        Wprev = genetateRandFill(n, c);&lt;br /&gt;
        W = Wprev;&lt;br /&gt;
        while (true){&lt;br /&gt;
            // обновляем центры кластеров &lt;br /&gt;
            for (int i=0; i&amp;lt;c; i++){&lt;br /&gt;
                float * num = new float []();&lt;br /&gt;
                float den = 0;&lt;br /&gt;
                for (int j=0; j&amp;lt;n; j++){&lt;br /&gt;
                    num += pow(W[j][i], m) * X[j];&lt;br /&gt;
                    den+=pow(W[j][i], m);&lt;br /&gt;
                }&lt;br /&gt;
                centers[i] = num / den;&lt;br /&gt;
            }&lt;br /&gt;
            //обновляем вероятности W и считаем расстояние между матрицами W и Wprev&lt;br /&gt;
            float max_diff = 0;&lt;br /&gt;
            for (int i=0; i&amp;lt;n; i++)&lt;br /&gt;
                for (int j=0; j&amp;lt;c; j++){&lt;br /&gt;
                    total = 0;&lt;br /&gt;
                    for (int m=0; m&amp;lt;с; m++)&lt;br /&gt;
                        total += pow(distance(X[i], centers[j]) / distance(X[i], centers[m]), 2/(m-1));&lt;br /&gt;
                    W[i][j] = 1/total;&lt;br /&gt;
                    max_diff = max(abs(Wprev[i][j]-W[i][j]), max_diff);&lt;br /&gt;
                    Wprev[i][j] = W[i][j];&lt;br /&gt;
               }               &lt;br /&gt;
           if (max_diff &amp;lt; eps):                &lt;br /&gt;
                break;&lt;br /&gt;
        }&lt;br /&gt;
        return W;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Последовательная сложность алгоритма состоит из сложности каждой итерации умноженной на их количество. Так как число итераций заранее неизвестно и зависит от входных параметров, рассмотрим сложность на каждой итерации. Наибольшую сложность представляет собой пересчет матрицы, сложность которого &amp;lt;math&amp;gt;O(c^2 nd)&amp;lt;/math&amp;gt; (по сравнению со сложностью &amp;lt;math&amp;gt;O(cnd)&amp;lt;/math&amp;gt; расчета расстояний, вычисления центроидов и проверки условия останова). Итого общая сложность алгоритма &amp;lt;math&amp;gt;O(c^2 ndi)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
Информационный граф представлен на рисунке ниже.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 1, 2, совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз для каждого кластера. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 1&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 2&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m*X_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем вектор размера &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; и матрицу размера &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;. &lt;br /&gt;
Далее совершаем поэлементное сложение векторов и матриц соответственно, а затем делим каждый столбец в матрице на соответствующий элемент в векторе.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй ярус&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 3, 4, 5 также совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 4&#039;&#039;&#039;: обновление значения &amp;lt;math&amp;gt;w_{ij}&amp;lt;/math&amp;gt; по указанной в разделе 1.2 в пункте 5 формуле.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 5&#039;&#039;&#039;: &amp;lt;math&amp;gt;maximum = max(|w_{ij} - w_{ij}^{prev}|, maximum)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 6&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^{prev} = w_{ij}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем число &amp;lt;math&amp;gt;maximum&amp;lt;/math&amp;gt;. Далее находим максимальное значение из полученных величин для каждой ветки. Затем проверяем условие останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:Scheme.JPG]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельная сложность алгоритма: &amp;lt;math&amp;gt;M*c^2*i&amp;lt;/math&amp;gt;. Такая сложность получается за счет распараллеливания на каждом ярусе &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; операций. Иерархическая структура параллелизма подробно описана в [[#Информационный граф|п.1.7]].&lt;br /&gt;
&lt;br /&gt;
В алгоритме не возникает скошенного параллелизма.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Входные данные алгоритма: набор векторов &amp;lt;math&amp;gt;x_i&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i = 1,...,M&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
* Выходные данные алгоритма: матрица вероятностей принадлежности векторов кластерам &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной формы алгоритма: &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;&lt;br /&gt;
* Вычислительная мощность: &amp;lt;math&amp;gt;{dc^2i} \over {c+d}&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Устойчивость: алгоритм не является устойчивым, поэтому существует много исследований о том, как первоначально выбрать параметры кластеризации.&lt;br /&gt;
* Сбалансированность: в данном алгоритме операция умножения доминирует над операцией сложения. Операции между параллельными ветвями сбалансированны.&lt;br /&gt;
* Детерминированность: алгоритм не является детерминированным, так как матрица нечеткого разбиение генерируется произвольно.&lt;br /&gt;
* Степень исхода вершины информационного графа ( для одной интерации): 2 (3 - с учетом, если выходные данные пошли на следующую итерацию).&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма = &lt;br /&gt;
&lt;br /&gt;
==Особенности реализации последовательного алгоритма==&lt;br /&gt;
&lt;br /&gt;
==Локальность данных и вычислений==&lt;br /&gt;
&lt;br /&gt;
==Возможные способы и особенности параллельной реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
==Динамические характеристики и эффективность реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
==Выводы для классов архитектур==&lt;br /&gt;
&lt;br /&gt;
==Существующие реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
* Реализация алгоритма на POSTGRESQL: http://num-meth.srcc.msu.ru/zhurnal/tom_2012/pdf/v13r207.pdf&lt;br /&gt;
* Библиотека для MATLAB: http://www.mathworks.com/help/fuzzy/fcm.html (распространяется на коммерческой основе)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=14554</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=14554"/>
		<updated>2016-10-28T16:12:23Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(Mdc^2i)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - количество итераций&lt;br /&gt;
| input_data         = &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt;, [количество наблюдений * размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt;, [количество наблюдений * количество кластеров]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;2i&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]] ([[#Вычислительное ядро алгоритма|1.3]]; [[#Схема реализации последовательного алгоритма|1.5]]; [[#Последовательная сложность алгоритма|1.6]]; [[#Информационный граф|1.7]]; [[#Масштабируемость алгоритма и его реализации|2.4]]; [[#Существующие реализации алгоритма|2.7]]), [[Участник:Yushin|Павел Юшин]] ([[#Общее описание алгоритма|1.1]]; [[#Математическое описание алгоритма|1.2]]; [[#Макроструктура алгоритма|1.4]]; [[#Ресурс параллелизма алгоритма|1.8]]; [[#Входные и выходные данные алгоритма|1.9]]; [[#Свойства алгоритма|1.10]])&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;{{Cite journal|last=Dunn|first=J. C.|date=1973-01-01|title=A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters|url=http://dx.doi.org/10.1080/01969727308546046|journal=Journal of Cybernetics|volume=3|issue=3|pages=32–57|doi=10.1080/01969727308546046|issn=0022-0280}}&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - экспоненциальный вес; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма будут отличать менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M&amp;lt;/math&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;0 &amp;lt; \sum_{i = 1}^M w_{ij} &amp;lt; M, j = 1, ..., c&amp;lt;/math&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда алгоритм принимает следующий вид:&lt;br /&gt;
&lt;br /&gt;
1) Задаем параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
2) Генерируем случайным образом матрицу нечеткого разбиения с учетом условий &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3) Рассчитываем центроиды (центры кластеров): &amp;lt;math&amp;gt;V_j = {{\sum_{i=1}^M w_{ij}^m * X_i} \over {\sum_{i=1}^M w_{ij}^m}}, j = 1, ..., c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Рассчитываем расстояния между объектами &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и центроидами:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_{ij} = {||X_i - V_j||}, i = 1,...,M; j = 1,...,c &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5) Пересчет элементов матрицы разбиения:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} &amp;gt;0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = {{1}\over {{ (\sum_{k=1}^c {{D_{ij}}\over{D_{ik}}} ) }^{2/(m-1)}}}, j = 1,...,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} =0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = \delta_{ij}, j = 1,...,c&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\delta_{ij}&amp;lt;/math&amp;gt; - символ Кронекера&lt;br /&gt;
&lt;br /&gt;
6) Если &amp;lt;math&amp;gt;|| F - F^{*} || &amp;lt; \varepsilon &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;F^{*}&amp;lt;/math&amp;gt; - матрица нечеткого разбиения предыдущей итерации, то идем далее, иначе возвращаемся на пункт 3.&lt;br /&gt;
&lt;br /&gt;
7) Конец.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром алгоритма являются пункты (3), (4), (5) - расчет центроидов, вычисление расстояний и пересчет элементов матрицы соответственно&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Основные шаги при реализации алгоритма&lt;br /&gt;
*	Генерация случайной матрицы размера &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на где &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;, проверка условий&lt;br /&gt;
*	Расчет центроидов – по сути, скалярное произведение с нормировкой&lt;br /&gt;
*	Расчет расстояний – в общепринятом случае является скалярным произведением&lt;br /&gt;
*	Пересчет матрицы – по сути, скалярное произведение&lt;br /&gt;
*	Проверка условий останова – вычисление нормы&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
    float ** FuzzyCMeans (float** X, c, m, eps){&lt;br /&gt;
        n = X.size();&lt;br /&gt;
        r = X[0].size();&lt;br /&gt;
        centers = generateZeroFill(c, r)&lt;br /&gt;
        Wprev = genetateRandFill(n, c);&lt;br /&gt;
        W = Wprev;&lt;br /&gt;
        while (true){&lt;br /&gt;
            // обновляем центры кластеров &lt;br /&gt;
            for (int i=0; i&amp;lt;c; i++){&lt;br /&gt;
                float * num = new float []();&lt;br /&gt;
                float den = 0;&lt;br /&gt;
                for (int j=0; j&amp;lt;n; j++){&lt;br /&gt;
                    num += pow(W[j][i], m) * X[j];&lt;br /&gt;
                    den+=pow(W[j][i], m);&lt;br /&gt;
                }&lt;br /&gt;
                centers[i] = num / den;&lt;br /&gt;
            }&lt;br /&gt;
            //обновляем вероятности W и считаем расстояние между матрицами W и Wprev&lt;br /&gt;
            float max_diff = 0;&lt;br /&gt;
            for (int i=0; i&amp;lt;n; i++)&lt;br /&gt;
                for (int j=0; j&amp;lt;c; j++){&lt;br /&gt;
                    total = 0;&lt;br /&gt;
                    for (int m=0; m&amp;lt;с; m++)&lt;br /&gt;
                        total += pow(distance(X[i], centers[j]) / distance(X[i], centers[m]), 2/(m-1));&lt;br /&gt;
                    W[i][j] = 1/total;&lt;br /&gt;
                    max_diff = max(abs(Wprev[i][j]-W[i][j]), max_diff);&lt;br /&gt;
                    Wprev[i][j] = W[i][j];&lt;br /&gt;
               }               &lt;br /&gt;
           if (max_diff &amp;lt; eps):                &lt;br /&gt;
                break;&lt;br /&gt;
        }&lt;br /&gt;
        return W;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Последовательная сложность алгоритма состоит из сложности каждой итерации умноженной на их количество. Так как число итераций заранее неизвестно и зависит от входных параметров, рассмотрим сложность на каждой итерации. Наибольшую сложность представляет собой пересчет матрицы, сложность которого &amp;lt;math&amp;gt;O(c^2 nd)&amp;lt;/math&amp;gt; (по сравнению со сложностью &amp;lt;math&amp;gt;O(cnd)&amp;lt;/math&amp;gt; расчета расстояний, вычисления центроидов и проверки условия останова). Итого общая сложность алгоритма &amp;lt;math&amp;gt;O(c^2 ndi)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
Информационный граф представлен на рисунке ниже.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 1, 2, совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз для каждого кластера. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 1&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 2&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m*X_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем вектор размера &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; и матрицу размера &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;. &lt;br /&gt;
Далее совершаем поэлементное сложение векторов и матриц соответственно, а затем делим каждый столбец в матрице на соответствующий элемент в векторе.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй ярус&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 3, 4, 5 также совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 4&#039;&#039;&#039;: обновление значения &amp;lt;math&amp;gt;w_{ij}&amp;lt;/math&amp;gt; по указанной в разделе 1.2 в пункте 5 формуле.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 5&#039;&#039;&#039;: &amp;lt;math&amp;gt;maximum = max(|w_{ij} - w_{ij}^{prev}|, maximum)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 6&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^{prev} = w_{ij}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем число &amp;lt;math&amp;gt;maximum&amp;lt;/math&amp;gt;. Далее находим максимальное значение из полученных величин для каждой ветки. Затем проверяем условие останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:Scheme.JPG]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельная сложность алгоритма: &amp;lt;math&amp;gt;M*c^2*i&amp;lt;/math&amp;gt;. Такая сложность получается за счет распараллеливания на каждом ярусе &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; операций. Иерархическая структура параллелизма подробно описана в [[#Информационный граф|п.1.7]].&lt;br /&gt;
&lt;br /&gt;
В алгоритме не возникает скошенного параллелизма.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Входные данные алгоритма: набор векторов &amp;lt;math&amp;gt;x_i&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i = 1,...,M&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
* Выходные данные алгоритма: матрица вероятностей принадлежности векторов кластерам &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной формы алгоритма: &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;&lt;br /&gt;
* Вычислительная мощность: &amp;lt;math&amp;gt;{dc^2i} \over {c+d}&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Устойчивость: алгоритм не является устойчивым, поэтому существует много исследований о том, как первоначально выбрать параметры кластеризации.&lt;br /&gt;
* Сбалансированность: в данном алгоритме операция умножения доминирует над операцией сложения. Операции между параллельными ветвями сбалансированны.&lt;br /&gt;
* Детерминированность: алгоритм не является детерминированным, так как матрица нечеткого разбиение генерируется произвольно.&lt;br /&gt;
* Степень исхода вершины информационного графа ( для одной интерации): 2 (3 - с учетом, если выходные данные пошли на следующую итерацию).&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма = &lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
==Существующие реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
* Реализация алгоритма на POSTGRESQL: http://num-meth.srcc.msu.ru/zhurnal/tom_2012/pdf/v13r207.pdf&lt;br /&gt;
* Библиотека для MATLAB: http://www.mathworks.com/help/fuzzy/fcm.html (распространяется на коммерческой основе)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=14553</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=14553"/>
		<updated>2016-10-28T16:09:20Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(Mdc^2i)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - количество итераций&lt;br /&gt;
| input_data         = &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt;, [количество наблюдений * размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt;, [количество наблюдений * количество кластеров]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;2i&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]] ([[#Вычислительное ядро алгоритма|1.3]]; [[1.5]]; [[1.6]]; [[1.7]]; [[2.4]]; [[2.7]]), [[Участник:Yushin|Павел Юшин]] ([[1.1]]; [[1.2]]; [[1.4]]; [[1.8]]; [[1.9]]; [[1.10]])&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;{{Cite journal|last=Dunn|first=J. C.|date=1973-01-01|title=A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters|url=http://dx.doi.org/10.1080/01969727308546046|journal=Journal of Cybernetics|volume=3|issue=3|pages=32–57|doi=10.1080/01969727308546046|issn=0022-0280}}&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - экспоненциальный вес; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма будут отличать менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M&amp;lt;/math&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;0 &amp;lt; \sum_{i = 1}^M w_{ij} &amp;lt; M, j = 1, ..., c&amp;lt;/math&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда алгоритм принимает следующий вид:&lt;br /&gt;
&lt;br /&gt;
1) Задаем параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
2) Генерируем случайным образом матрицу нечеткого разбиения с учетом условий &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3) Рассчитываем центроиды (центры кластеров): &amp;lt;math&amp;gt;V_j = {{\sum_{i=1}^M w_{ij}^m * X_i} \over {\sum_{i=1}^M w_{ij}^m}}, j = 1, ..., c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Рассчитываем расстояния между объектами &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и центроидами:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_{ij} = {||X_i - V_j||}, i = 1,...,M; j = 1,...,c &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5) Пересчет элементов матрицы разбиения:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} &amp;gt;0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = {{1}\over {{ (\sum_{k=1}^c {{D_{ij}}\over{D_{ik}}} ) }^{2/(m-1)}}}, j = 1,...,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} =0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = \delta_{ij}, j = 1,...,c&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\delta_{ij}&amp;lt;/math&amp;gt; - символ Кронекера&lt;br /&gt;
&lt;br /&gt;
6) Если &amp;lt;math&amp;gt;|| F - F^{*} || &amp;lt; \varepsilon &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;F^{*}&amp;lt;/math&amp;gt; - матрица нечеткого разбиения предыдущей итерации, то идем далее, иначе возвращаемся на пункт 3.&lt;br /&gt;
&lt;br /&gt;
7) Конец.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром алгоритма являются пункты (3), (4), (5) - расчет центроидов, вычисление расстояний и пересчет элементов матрицы соответственно&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Основные шаги при реализации алгоритма&lt;br /&gt;
*	Генерация случайной матрицы размера &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на где &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;, проверка условий&lt;br /&gt;
*	Расчет центроидов – по сути, скалярное произведение с нормировкой&lt;br /&gt;
*	Расчет расстояний – в общепринятом случае является скалярным произведением&lt;br /&gt;
*	Пересчет матрицы – по сути, скалярное произведение&lt;br /&gt;
*	Проверка условий останова – вычисление нормы&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
    float ** FuzzyCMeans (float** X, c, m, eps){&lt;br /&gt;
        n = X.size();&lt;br /&gt;
        r = X[0].size();&lt;br /&gt;
        centers = generateZeroFill(c, r)&lt;br /&gt;
        Wprev = genetateRandFill(n, c);&lt;br /&gt;
        W = Wprev;&lt;br /&gt;
        while (true){&lt;br /&gt;
            // обновляем центры кластеров &lt;br /&gt;
            for (int i=0; i&amp;lt;c; i++){&lt;br /&gt;
                float * num = new float []();&lt;br /&gt;
                float den = 0;&lt;br /&gt;
                for (int j=0; j&amp;lt;n; j++){&lt;br /&gt;
                    num += pow(W[j][i], m) * X[j];&lt;br /&gt;
                    den+=pow(W[j][i], m);&lt;br /&gt;
                }&lt;br /&gt;
                centers[i] = num / den;&lt;br /&gt;
            }&lt;br /&gt;
            //обновляем вероятности W и считаем расстояние между матрицами W и Wprev&lt;br /&gt;
            float max_diff = 0;&lt;br /&gt;
            for (int i=0; i&amp;lt;n; i++)&lt;br /&gt;
                for (int j=0; j&amp;lt;c; j++){&lt;br /&gt;
                    total = 0;&lt;br /&gt;
                    for (int m=0; m&amp;lt;с; m++)&lt;br /&gt;
                        total += pow(distance(X[i], centers[j]) / distance(X[i], centers[m]), 2/(m-1));&lt;br /&gt;
                    W[i][j] = 1/total;&lt;br /&gt;
                    max_diff = max(abs(Wprev[i][j]-W[i][j]), max_diff);&lt;br /&gt;
                    Wprev[i][j] = W[i][j];&lt;br /&gt;
               }               &lt;br /&gt;
           if (max_diff &amp;lt; eps):                &lt;br /&gt;
                break;&lt;br /&gt;
        }&lt;br /&gt;
        return W;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Последовательная сложность алгоритма состоит из сложности каждой итерации умноженной на их количество. Так как число итераций заранее неизвестно и зависит от входных параметров, рассмотрим сложность на каждой итерации. Наибольшую сложность представляет собой пересчет матрицы, сложность которого &amp;lt;math&amp;gt;O(c^2 nd)&amp;lt;/math&amp;gt; (по сравнению со сложностью &amp;lt;math&amp;gt;O(cnd)&amp;lt;/math&amp;gt; расчета расстояний, вычисления центроидов и проверки условия останова). Итого общая сложность алгоритма &amp;lt;math&amp;gt;O(c^2 ndi)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
Информационный граф представлен на рисунке ниже.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 1, 2, совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз для каждого кластера. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 1&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 2&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m*X_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем вектор размера &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; и матрицу размера &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;. &lt;br /&gt;
Далее совершаем поэлементное сложение векторов и матриц соответственно, а затем делим каждый столбец в матрице на соответствующий элемент в векторе.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй ярус&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 3, 4, 5 также совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 4&#039;&#039;&#039;: обновление значения &amp;lt;math&amp;gt;w_{ij}&amp;lt;/math&amp;gt; по указанной в разделе 1.2 в пункте 5 формуле.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 5&#039;&#039;&#039;: &amp;lt;math&amp;gt;maximum = max(|w_{ij} - w_{ij}^{prev}|, maximum)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 6&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^{prev} = w_{ij}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем число &amp;lt;math&amp;gt;maximum&amp;lt;/math&amp;gt;. Далее находим максимальное значение из полученных величин для каждой ветки. Затем проверяем условие останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:Scheme.JPG]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельная сложность алгоритма: &amp;lt;math&amp;gt;M*c^2*i&amp;lt;/math&amp;gt;. Такая сложность получается за счет распараллеливания на каждом ярусе &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; операций. Иерархическая структура параллелизма подробно описана в [[#Информационный граф|п.1.7]].&lt;br /&gt;
&lt;br /&gt;
В алгоритме не возникает скошенного параллелизма.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Входные данные алгоритма: набор векторов &amp;lt;math&amp;gt;x_i&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i = 1,...,M&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
* Выходные данные алгоритма: матрица вероятностей принадлежности векторов кластерам &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной формы алгоритма: &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;&lt;br /&gt;
* Вычислительная мощность: &amp;lt;math&amp;gt;{dc^2i} \over {c+d}&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Устойчивость: алгоритм не является устойчивым, поэтому существует много исследований о том, как первоначально выбрать параметры кластеризации.&lt;br /&gt;
* Сбалансированность: в данном алгоритме операция умножения доминирует над операцией сложения. Операции между параллельными ветвями сбалансированны.&lt;br /&gt;
* Детерминированность: алгоритм не является детерминированным, так как матрица нечеткого разбиение генерируется произвольно.&lt;br /&gt;
* Степень исхода вершины информационного графа ( для одной интерации): 2 (3 - с учетом, если выходные данные пошли на следующую итерацию).&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма = &lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
==Существующие реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
* Реализация алгоритма на POSTGRESQL: http://num-meth.srcc.msu.ru/zhurnal/tom_2012/pdf/v13r207.pdf&lt;br /&gt;
* Библиотека для MATLAB: http://www.mathworks.com/help/fuzzy/fcm.html (распространяется на коммерческой основе)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=14552</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=14552"/>
		<updated>2016-10-28T16:06:40Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(Mdc^2i)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - количество итераций&lt;br /&gt;
| input_data         = &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt;, [количество наблюдений * размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt;, [количество наблюдений * количество кластеров]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;2i&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]] (1.3; 1.5; 1.6; 1.7; 2.4; 2.7), [[Участник:Yushin|Павел Юшин]] (1.1; 1.2; 1.4; 1.8; 1.9; 1.10)&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;{{Cite journal|last=Dunn|first=J. C.|date=1973-01-01|title=A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters|url=http://dx.doi.org/10.1080/01969727308546046|journal=Journal of Cybernetics|volume=3|issue=3|pages=32–57|doi=10.1080/01969727308546046|issn=0022-0280}}&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - экспоненциальный вес; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма будут отличать менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M&amp;lt;/math&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;0 &amp;lt; \sum_{i = 1}^M w_{ij} &amp;lt; M, j = 1, ..., c&amp;lt;/math&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда алгоритм принимает следующий вид:&lt;br /&gt;
&lt;br /&gt;
1) Задаем параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
2) Генерируем случайным образом матрицу нечеткого разбиения с учетом условий &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3) Рассчитываем центроиды (центры кластеров): &amp;lt;math&amp;gt;V_j = {{\sum_{i=1}^M w_{ij}^m * X_i} \over {\sum_{i=1}^M w_{ij}^m}}, j = 1, ..., c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Рассчитываем расстояния между объектами &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и центроидами:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_{ij} = {||X_i - V_j||}, i = 1,...,M; j = 1,...,c &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5) Пересчет элементов матрицы разбиения:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} &amp;gt;0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = {{1}\over {{ (\sum_{k=1}^c {{D_{ij}}\over{D_{ik}}} ) }^{2/(m-1)}}}, j = 1,...,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} =0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = \delta_{ij}, j = 1,...,c&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\delta_{ij}&amp;lt;/math&amp;gt; - символ Кронекера&lt;br /&gt;
&lt;br /&gt;
6) Если &amp;lt;math&amp;gt;|| F - F^{*} || &amp;lt; \varepsilon &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;F^{*}&amp;lt;/math&amp;gt; - матрица нечеткого разбиения предыдущей итерации, то идем далее, иначе возвращаемся на пункт 3.&lt;br /&gt;
&lt;br /&gt;
7) Конец.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром алгоритма являются пункты (3), (4), (5) - расчет центроидов, вычисление расстояний и пересчет элементов матрицы соответственно&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Основные шаги при реализации алгоритма&lt;br /&gt;
*	Генерация случайной матрицы размера &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на где &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;, проверка условий&lt;br /&gt;
*	Расчет центроидов – по сути, скалярное произведение с нормировкой&lt;br /&gt;
*	Расчет расстояний – в общепринятом случае является скалярным произведением&lt;br /&gt;
*	Пересчет матрицы – по сути, скалярное произведение&lt;br /&gt;
*	Проверка условий останова – вычисление нормы&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
    float ** FuzzyCMeans (float** X, c, m, eps){&lt;br /&gt;
        n = X.size();&lt;br /&gt;
        r = X[0].size();&lt;br /&gt;
        centers = generateZeroFill(c, r)&lt;br /&gt;
        Wprev = genetateRandFill(n, c);&lt;br /&gt;
        W = Wprev;&lt;br /&gt;
        while (true){&lt;br /&gt;
            // обновляем центры кластеров &lt;br /&gt;
            for (int i=0; i&amp;lt;c; i++){&lt;br /&gt;
                float * num = new float []();&lt;br /&gt;
                float den = 0;&lt;br /&gt;
                for (int j=0; j&amp;lt;n; j++){&lt;br /&gt;
                    num += pow(W[j][i], m) * X[j];&lt;br /&gt;
                    den+=pow(W[j][i], m);&lt;br /&gt;
                }&lt;br /&gt;
                centers[i] = num / den;&lt;br /&gt;
            }&lt;br /&gt;
            //обновляем вероятности W и считаем расстояние между матрицами W и Wprev&lt;br /&gt;
            float max_diff = 0;&lt;br /&gt;
            for (int i=0; i&amp;lt;n; i++)&lt;br /&gt;
                for (int j=0; j&amp;lt;c; j++){&lt;br /&gt;
                    total = 0;&lt;br /&gt;
                    for (int m=0; m&amp;lt;с; m++)&lt;br /&gt;
                        total += pow(distance(X[i], centers[j]) / distance(X[i], centers[m]), 2/(m-1));&lt;br /&gt;
                    W[i][j] = 1/total;&lt;br /&gt;
                    max_diff = max(abs(Wprev[i][j]-W[i][j]), max_diff);&lt;br /&gt;
                    Wprev[i][j] = W[i][j];&lt;br /&gt;
               }               &lt;br /&gt;
           if (max_diff &amp;lt; eps):                &lt;br /&gt;
                break;&lt;br /&gt;
        }&lt;br /&gt;
        return W;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Последовательная сложность алгоритма состоит из сложности каждой итерации умноженной на их количество. Так как число итераций заранее неизвестно и зависит от входных параметров, рассмотрим сложность на каждой итерации. Наибольшую сложность представляет собой пересчет матрицы, сложность которого &amp;lt;math&amp;gt;O(c^2 nd)&amp;lt;/math&amp;gt; (по сравнению со сложностью &amp;lt;math&amp;gt;O(cnd)&amp;lt;/math&amp;gt; расчета расстояний, вычисления центроидов и проверки условия останова). Итого общая сложность алгоритма &amp;lt;math&amp;gt;O(c^2 ndi)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
Информационный граф представлен на рисунке ниже.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 1, 2, совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз для каждого кластера. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 1&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 2&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m*X_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем вектор размера &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; и матрицу размера &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;. &lt;br /&gt;
Далее совершаем поэлементное сложение векторов и матриц соответственно, а затем делим каждый столбец в матрице на соответствующий элемент в векторе.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй ярус&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 3, 4, 5 также совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 4&#039;&#039;&#039;: обновление значения &amp;lt;math&amp;gt;w_{ij}&amp;lt;/math&amp;gt; по указанной в разделе 1.2 в пункте 5 формуле.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 5&#039;&#039;&#039;: &amp;lt;math&amp;gt;maximum = max(|w_{ij} - w_{ij}^{prev}|, maximum)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 6&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^{prev} = w_{ij}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем число &amp;lt;math&amp;gt;maximum&amp;lt;/math&amp;gt;. Далее находим максимальное значение из полученных величин для каждой ветки. Затем проверяем условие останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:Scheme.JPG]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельная сложность алгоритма: &amp;lt;math&amp;gt;M*c^2*i&amp;lt;/math&amp;gt;. Такая сложность получается за счет распараллеливания на каждом ярусе &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; операций. Иерархическая структура параллелизма подробно описана в [[#Информационный граф|п.1.7]].&lt;br /&gt;
&lt;br /&gt;
В алгоритме не возникает скошенного параллелизма.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Входные данные алгоритма: набор векторов &amp;lt;math&amp;gt;x_i&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i = 1,...,M&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
* Выходные данные алгоритма: матрица вероятностей принадлежности векторов кластерам &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной формы алгоритма: &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;&lt;br /&gt;
* Вычислительная мощность: &amp;lt;math&amp;gt;{dc^2i} \over {c+d}&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Устойчивость: алгоритм не является устойчивым, поэтому существует много исследований о том, как первоначально выбрать параметры кластеризации.&lt;br /&gt;
* Сбалансированность: в данном алгоритме операция умножения доминирует над операцией сложения. Операции между параллельными ветвями сбалансированны.&lt;br /&gt;
* Детерминированность: алгоритм не является детерминированным, так как матрица нечеткого разбиение генерируется произвольно.&lt;br /&gt;
* Степень исхода вершины информационного графа ( для одной интерации): 2 (3 - с учетом, если выходные данные пошли на следующую итерацию).&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма = &lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
==Существующие реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
* Реализация алгоритма на POSTGRESQL: http://num-meth.srcc.msu.ru/zhurnal/tom_2012/pdf/v13r207.pdf&lt;br /&gt;
* Библиотека для MATLAB: http://www.mathworks.com/help/fuzzy/fcm.html (распространяется на коммерческой основе)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=14551</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=14551"/>
		<updated>2016-10-28T15:57:33Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(Mdc^2i)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - количество итераций&lt;br /&gt;
| input_data         = &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt;, [количество наблюдений * размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt;, [количество наблюдений * количество кластеров]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;2i&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]], [[Участник:Yushin|Павел Юшин]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;{{Cite journal|last=Dunn|first=J. C.|date=1973-01-01|title=A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters|url=http://dx.doi.org/10.1080/01969727308546046|journal=Journal of Cybernetics|volume=3|issue=3|pages=32–57|doi=10.1080/01969727308546046|issn=0022-0280}}&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - экспоненциальный вес; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма будут отличать менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M&amp;lt;/math&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;0 &amp;lt; \sum_{i = 1}^M w_{ij} &amp;lt; M, j = 1, ..., c&amp;lt;/math&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда алгоритм принимает следующий вид:&lt;br /&gt;
&lt;br /&gt;
1) Задаем параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
2) Генерируем случайным образом матрицу нечеткого разбиения с учетом условий &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3) Рассчитываем центроиды (центры кластеров): &amp;lt;math&amp;gt;V_j = {{\sum_{i=1}^M w_{ij}^m * X_i} \over {\sum_{i=1}^M w_{ij}^m}}, j = 1, ..., c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Рассчитываем расстояния между объектами &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и центроидами:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_{ij} = {||X_i - V_j||}, i = 1,...,M; j = 1,...,c &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5) Пересчет элементов матрицы разбиения:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} &amp;gt;0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = {{1}\over {{ (\sum_{k=1}^c {{D_{ij}}\over{D_{ik}}} ) }^{2/(m-1)}}}, j = 1,...,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} =0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = \delta_{ij}, j = 1,...,c&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\delta_{ij}&amp;lt;/math&amp;gt; - символ Кронекера&lt;br /&gt;
&lt;br /&gt;
6) Если &amp;lt;math&amp;gt;|| F - F^{*} || &amp;lt; \varepsilon &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;F^{*}&amp;lt;/math&amp;gt; - матрица нечеткого разбиения предыдущей итерации, то идем далее, иначе возвращаемся на пункт 3.&lt;br /&gt;
&lt;br /&gt;
7) Конец.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром алгоритма являются пункты (3), (4), (5) - расчет центроидов, вычисление расстояний и пересчет элементов матрицы соответственно&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Основные шаги при реализации алгоритма&lt;br /&gt;
*	Генерация случайной матрицы размера &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на где &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;, проверка условий&lt;br /&gt;
*	Расчет центроидов – по сути, скалярное произведение с нормировкой&lt;br /&gt;
*	Расчет расстояний – в общепринятом случае является скалярным произведением&lt;br /&gt;
*	Пересчет матрицы – по сути, скалярное произведение&lt;br /&gt;
*	Проверка условий останова – вычисление нормы&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
    float ** FuzzyCMeans (float** X, c, m, eps){&lt;br /&gt;
        n = X.size();&lt;br /&gt;
        r = X[0].size();&lt;br /&gt;
        centers = generateZeroFill(c, r)&lt;br /&gt;
        Wprev = genetateRandFill(n, c);&lt;br /&gt;
        W = Wprev;&lt;br /&gt;
        while (true){&lt;br /&gt;
            // обновляем центры кластеров &lt;br /&gt;
            for (int i=0; i&amp;lt;c; i++){&lt;br /&gt;
                float * num = new float []();&lt;br /&gt;
                float den = 0;&lt;br /&gt;
                for (int j=0; j&amp;lt;n; j++){&lt;br /&gt;
                    num += pow(W[j][i], m) * X[j];&lt;br /&gt;
                    den+=pow(W[j][i], m);&lt;br /&gt;
                }&lt;br /&gt;
                centers[i] = num / den;&lt;br /&gt;
            }&lt;br /&gt;
            //обновляем вероятности W и считаем расстояние между матрицами W и Wprev&lt;br /&gt;
            float max_diff = 0;&lt;br /&gt;
            for (int i=0; i&amp;lt;n; i++)&lt;br /&gt;
                for (int j=0; j&amp;lt;c; j++){&lt;br /&gt;
                    total = 0;&lt;br /&gt;
                    for (int m=0; m&amp;lt;с; m++)&lt;br /&gt;
                        total += pow(distance(X[i], centers[j]) / distance(X[i], centers[m]), 2/(m-1));&lt;br /&gt;
                    W[i][j] = 1/total;&lt;br /&gt;
                    max_diff = max(abs(Wprev[i][j]-W[i][j]), max_diff);&lt;br /&gt;
                    Wprev[i][j] = W[i][j];&lt;br /&gt;
               }               &lt;br /&gt;
           if (max_diff &amp;lt; eps):                &lt;br /&gt;
                break;&lt;br /&gt;
        }&lt;br /&gt;
        return W;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Последовательная сложность алгоритма состоит из сложности каждой итерации умноженной на их количество. Так как число итераций заранее неизвестно и зависит от входных параметров, рассмотрим сложность на каждой итерации. Наибольшую сложность представляет собой пересчет матрицы, сложность которого &amp;lt;math&amp;gt;O(c^2 nd)&amp;lt;/math&amp;gt; (по сравнению со сложностью &amp;lt;math&amp;gt;O(cnd)&amp;lt;/math&amp;gt; расчета расстояний, вычисления центроидов и проверки условия останова). Итого общая сложность алгоритма &amp;lt;math&amp;gt;O(c^2 ndi)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
Информационный граф представлен на рисунке ниже.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 1, 2, совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз для каждого кластера. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 1&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 2&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m*X_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем вектор размера &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; и матрицу размера &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;. &lt;br /&gt;
Далее совершаем поэлементное сложение векторов и матриц соответственно, а затем делим каждый столбец в матрице на соответствующий элемент в векторе.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй ярус&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 3, 4, 5 также совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 4&#039;&#039;&#039;: обновление значения &amp;lt;math&amp;gt;w_{ij}&amp;lt;/math&amp;gt; по указанной в разделе 1.2 в пункте 5 формуле.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 5&#039;&#039;&#039;: &amp;lt;math&amp;gt;maximum = max(|w_{ij} - w_{ij}^{prev}|, maximum)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 6&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^{prev} = w_{ij}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем число &amp;lt;math&amp;gt;maximum&amp;lt;/math&amp;gt;. Далее находим максимальное значение из полученных величин для каждой ветки. Затем проверяем условие останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:Scheme.JPG]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельная сложность алгоритма: &amp;lt;math&amp;gt;M*c^2*i&amp;lt;/math&amp;gt;. Такая сложность получается за счет распараллеливания на каждом ярусе &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; операций. Иерархическая структура параллелизма подробно описана в [[#Информационный граф|п.1.7]].&lt;br /&gt;
&lt;br /&gt;
В алгоритме не возникает скошенного параллелизма.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Входные данные алгоритма: набор векторов &amp;lt;math&amp;gt;x_i&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i = 1,...,M&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
* Выходные данные алгоритма: матрица вероятностей принадлежности векторов кластерам &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной формы алгоритма: &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;&lt;br /&gt;
* Вычислительная мощность: &amp;lt;math&amp;gt;{dc^2i} \over {c+d}&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Устойчивость: алгоритм не является устойчивым, поэтому существует много исследований о том, как первоначально выбрать параметры кластеризации.&lt;br /&gt;
* Сбалансированность: в данном алгоритме операция умножения доминирует над операцией сложения. Операции между параллельными ветвями сбалансированны.&lt;br /&gt;
* Детерминированность: алгоритм не является детерминированным, так как матрица нечеткого разбиение генерируется произвольно.&lt;br /&gt;
* Степень исхода вершины информационного графа ( для одной интерации): 2 (3 - с учетом, если выходные данные пошли на следующую итерацию).&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма = &lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
==Существующие реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
* Реализация алгоритма на POSTGRESQL: http://num-meth.srcc.msu.ru/zhurnal/tom_2012/pdf/v13r207.pdf&lt;br /&gt;
* Библиотека для MATLAB: http://www.mathworks.com/help/fuzzy/fcm.html (распространяется на коммерческой основе)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=9535</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=9535"/>
		<updated>2016-10-15T12:45:16Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(Mdc^2i)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - количество итераций&lt;br /&gt;
| input_data         = &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt;, [количество наблюдений * размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt;, [количество наблюдений * количество кластеров]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;2i&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]], [[Участник:Yushin|Павел Юшин]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;{{Cite journal|last=Dunn|first=J. C.|date=1973-01-01|title=A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters|url=http://dx.doi.org/10.1080/01969727308546046|journal=Journal of Cybernetics|volume=3|issue=3|pages=32–57|doi=10.1080/01969727308546046|issn=0022-0280}}&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - экспоненциальный вес; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма будут отличать менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;0 &amp;lt; \sum_{i = 1}^M w_{ij} &amp;lt; M, j = 1, ..., c&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда алгоритм принимает следующий вид:&lt;br /&gt;
&lt;br /&gt;
1) Задаем параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
2) Генерируем случайным образом матрицу нечеткого разбиения с учетом условий &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3) Рассчитываем центроиды (центры кластеров): &amp;lt;math&amp;gt;V_j = {{\sum_{i=1}^M w_{ij}^m * X_i} \over {\sum_{i=1}^M w_{ij}^m}}, j = 1, ..., c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Рассчитываем расстояния между объектами &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и центроидами:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_{ij} = {||X_i - V_j||}, i = 1,...,M; j = 1,...,c &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5) Пересчет элементов матрицы разбиения:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} &amp;gt;0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = {{1}\over {{ (\sum_{k=1}^c {{D_{ij}}\over{D_{ik}}} ) }^{2/(m-1)}}}, j = 1,...,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} =0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = \delta_{ij}, j = 1,...,c&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\delta_{ij}&amp;lt;/math&amp;gt; - символ Кронекера&lt;br /&gt;
&lt;br /&gt;
6) Если &amp;lt;math&amp;gt;|| F - F^{*} || &amp;lt; \varepsilon &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;F^{*}&amp;lt;/math&amp;gt; - матрица нечеткого разбиения предыдущей итерации, то идем далее, иначе возвращаемся на пункт 3.&lt;br /&gt;
&lt;br /&gt;
7) Конец.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром алгоритма являются пункты (3), (4), (5) - расчет центроидов, вычисление расстояний и пересчет элементов матрицы соответственно&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Основные шаги при реализации алгоритма&lt;br /&gt;
*	Генерация случайной матрицы размера &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на где &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;, проверка условий&lt;br /&gt;
*	Расчет центроидов – по сути, скалярное произведение с нормировкой&lt;br /&gt;
*	Расчет расстояний – в общепринятом случае является скалярным произведением&lt;br /&gt;
*	Пересчет матрицы – по сути, скалярное произведение&lt;br /&gt;
*	Проверка условий останова – вычисление нормы&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
    float ** FuzzyCMeans (float** X, c, m, eps){&lt;br /&gt;
        n = X.size();&lt;br /&gt;
        r = X[0].size();&lt;br /&gt;
        centers = generateZeroFill(c, r)&lt;br /&gt;
        Wprev = genetateRandFill(n, c);&lt;br /&gt;
        W = Wprev;&lt;br /&gt;
        while (true){&lt;br /&gt;
            // обновляем центры кластеров &lt;br /&gt;
            for (int i=0; i&amp;lt;c; i++){&lt;br /&gt;
                float * num = new float []();&lt;br /&gt;
                float den = 0;&lt;br /&gt;
                for (int j=0; j&amp;lt;n; j++){&lt;br /&gt;
                    num += pow(W[j][i], m) * X[j];&lt;br /&gt;
                    den+=pow(W[j][i], m);&lt;br /&gt;
                }&lt;br /&gt;
                centers[i] = num / den;&lt;br /&gt;
            }&lt;br /&gt;
            //обновляем вероятности W и считаем расстояние между матрицами W и Wprev&lt;br /&gt;
            float max_diff = 0;&lt;br /&gt;
            for (int i=0; i&amp;lt;n; i++)&lt;br /&gt;
                for (int j=0; j&amp;lt;c; j++){&lt;br /&gt;
                    total = 0;&lt;br /&gt;
                    for (int m=0; m&amp;lt;с; m++)&lt;br /&gt;
                        total += pow(distance(X[i], centers[j]) / distance(X[i], centers[m]), 2/(m-1));&lt;br /&gt;
                    W[i][j] = 1/total;&lt;br /&gt;
                    max_diff = max(abs(Wprev[i][j]-W[i][j]), max_diff);&lt;br /&gt;
                    Wprev[i][j] = W[i][j];&lt;br /&gt;
               }               &lt;br /&gt;
           if (max_diff &amp;lt; eps):                &lt;br /&gt;
                break;&lt;br /&gt;
        }&lt;br /&gt;
        return W;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Последовательная сложность алгоритма состоит из сложности каждой итерации умноженной на их количество. Так как число итераций заранее неизвестно и зависит от входных параметров, рассмотрим сложность на каждой итерации. Наибольшую сложность представляет собой пересчет матрицы, сложность которого &amp;lt;math&amp;gt;O(c^2 nd)&amp;lt;/math&amp;gt; (по сравнению со сложностью &amp;lt;math&amp;gt;O(cnd)&amp;lt;/math&amp;gt; расчета расстояний, вычисления центроидов и проверки условия останова). Итого общая сложность алгоритма &amp;lt;math&amp;gt;O(c^2 ndi)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
Информационный граф представлен на рисунке ниже.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 1, 2, совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз для каждого кластера. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 1&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 2&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m*X_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем вектор размера &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; и матрицу размера &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;. &lt;br /&gt;
Далее совершаем поэлементное сложение векторов и матриц соответственно, а затем делим каждый столбец в матрице на соответствующий элемент в векторе.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй ярус&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 3, 4, 5 также совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 4&#039;&#039;&#039;: обновление значения &amp;lt;math&amp;gt;w_{ij}&amp;lt;/math&amp;gt; по указанной в разделе 1.2 в пункте 5 формуле.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 5&#039;&#039;&#039;: &amp;lt;math&amp;gt;maximum = max(|w_{ij} - w_{ij}^{prev}|, maximum)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 6&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^{prev} = w_{ij}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем число &amp;lt;math&amp;gt;maximum&amp;lt;/math&amp;gt;. Далее находим максимальное значение из полученных величин для каждой ветки. Затем проверяем условие останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:Scheme.JPG]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельная сложность алгоритма: &amp;lt;math&amp;gt;M*c^2*i&amp;lt;/math&amp;gt;. Такая сложность получается за счет распараллеливания на каждом ярусе &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; операций. Иерархическая структура параллелизма подробно описана в [[#Информационный граф|п.1.7]].&lt;br /&gt;
&lt;br /&gt;
В алгоритме не возникает скошенного параллелизма.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Входные данные алгоритма: набор векторов &amp;lt;math&amp;gt;x_i&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i = 1,...,M&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
* Выходные данные алгоритма: матрица вероятностей принадлежности векторов кластерам &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной формы алгоритма: &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;&lt;br /&gt;
* Вычислительная мощность: &amp;lt;math&amp;gt;{dc^2i} \over {c+d}&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Устойчивость: алгоритм не является устойчивым, поэтому существует много исследований о том, как первоначально выбрать параметры кластеризации.&lt;br /&gt;
* Сбалансированность: в данном алгоритме операция умножения доминирует над операцией сложения. Операции между параллельными ветвями сбалансированны.&lt;br /&gt;
* Детерминированность: алгоритм не является детерминированным, так как матрица нечеткого разбиение генерируется произвольно.&lt;br /&gt;
* Степень исхода вершины информационного графа ( для одной интерации): 2 (3 - с учетом, если выходные данные пошли на следующую итерацию).&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма = &lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
==Существующие реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
* Реализация алгоритма на POSTGRESQL: http://num-meth.srcc.msu.ru/zhurnal/tom_2012/pdf/v13r207.pdf&lt;br /&gt;
* Библиотека для MATLAB: http://www.mathworks.com/help/fuzzy/fcm.html (распространяется на коммерческой основе)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=9530</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=9530"/>
		<updated>2016-10-15T12:43:44Z</updated>

		<summary type="html">&lt;p&gt;Yushin: /* Ресурс параллелизма алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(Mdc^2i)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - количество итераций&lt;br /&gt;
| input_data         = &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt;, [количество наблюдений * размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt;, [количество наблюдений * количество кластеров]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;2i&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]], [[Участник:Yushin|Павел Юшин]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;{{Cite journal|last=Dunn|first=J. C.|date=1973-01-01|title=A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters|url=http://dx.doi.org/10.1080/01969727308546046|journal=Journal of Cybernetics|volume=3|issue=3|pages=32–57|doi=10.1080/01969727308546046|issn=0022-0280}}&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - экспоненциальный вес; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма будут отличать менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;0 &amp;lt; \sum_{i = 1}^M w_{ij} &amp;lt; M, j = 1, ..., c&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда алгоритм принимает следующий вид:&lt;br /&gt;
&lt;br /&gt;
1) Задаем параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
2) Генерируем случайным образом матрицу нечеткого разбиения с учетом условий &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3) Рассчитываем центроиды (центры кластеров): &amp;lt;math&amp;gt;V_j = {{\sum_{i=1}^M w_{ij}^m * X_i} \over {\sum_{i=1}^M w_{ij}^m}}, j = 1, ..., c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Рассчитываем расстояния между объектами &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и центроидами:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_{ij} = {||X_i - V_j||}, i = 1,...,M; j = 1,...,c &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5) Пересчет элементов матрицы разбиения:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} &amp;gt;0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = {{1}\over {{ (\sum_{k=1}^c {{D_{ij}}\over{D_{ik}}} ) }^{2/(m-1)}}}, j = 1,...,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} =0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = \delta_{ij}, j = 1,...,c&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\delta_{ij}&amp;lt;/math&amp;gt; - символ Кронекера&lt;br /&gt;
&lt;br /&gt;
6) Если &amp;lt;math&amp;gt;|| F - F^{*} || &amp;lt; \varepsilon &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;F^{*}&amp;lt;/math&amp;gt; - матрица нечеткого разбиения предыдущей итерации, то идем далее, иначе возвращаемся на пункт 3.&lt;br /&gt;
&lt;br /&gt;
7) Конец.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром алгоритма являются пункты (3), (4), (5) - расчет центроидов, вычисление расстояний и пересчет элементов матрицы соответственно&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Основные шаги при реализации алгоритма&lt;br /&gt;
*	Генерация случайной матрицы размера &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на где &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;, проверка условий&lt;br /&gt;
*	Расчет центроидов – по сути, скалярное произведение с нормировкой&lt;br /&gt;
*	Расчет расстояний – в общепринятом случае является скалярным произведением&lt;br /&gt;
*	Пересчет матрицы – по сути, скалярное произведение&lt;br /&gt;
*	Проверка условий останова – вычисление нормы&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
    float ** FuzzyCMeans (float** X, c, m, eps){&lt;br /&gt;
        n = X.size();&lt;br /&gt;
        r = X[0].size();&lt;br /&gt;
        centers = generateZeroFill(c, r)&lt;br /&gt;
        Wprev = genetateRandFill(n, c);&lt;br /&gt;
        W = Wprev;&lt;br /&gt;
        while (true){&lt;br /&gt;
            // обновляем центры кластеров &lt;br /&gt;
            for (int i=0; i&amp;lt;c; i++){&lt;br /&gt;
                float * num = new float []();&lt;br /&gt;
                float den = 0;&lt;br /&gt;
                for (int j=0; j&amp;lt;n; j++){&lt;br /&gt;
                    num += pow(W[j][i], m) * X[j];&lt;br /&gt;
                    den+=pow(W[j][i], m);&lt;br /&gt;
                }&lt;br /&gt;
                centers[i] = num / den;&lt;br /&gt;
            }&lt;br /&gt;
            //обновляем вероятности W и считаем расстояние между матрицами W и Wprev&lt;br /&gt;
            float max_diff = 0;&lt;br /&gt;
            for (int i=0; i&amp;lt;n; i++)&lt;br /&gt;
                for (int j=0; j&amp;lt;c; j++){&lt;br /&gt;
                    total = 0;&lt;br /&gt;
                    for (int m=0; m&amp;lt;с; m++)&lt;br /&gt;
                        total += pow(distance(X[i], centers[j]) / distance(X[i], centers[m]), 2/(m-1));&lt;br /&gt;
                    W[i][j] = 1/total;&lt;br /&gt;
                    max_diff = max(abs(Wprev[i][j]-W[i][j]), max_diff);&lt;br /&gt;
                    Wprev[i][j] = W[i][j];&lt;br /&gt;
               }               &lt;br /&gt;
           if (max_diff &amp;lt; eps):                &lt;br /&gt;
                break;&lt;br /&gt;
        }&lt;br /&gt;
        return W;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Последовательная сложность алгоритма состоит из сложности каждой итерации умноженной на их количество. Так как число итераций заранее неизвестно и зависит от входных параметров, рассмотрим сложность на каждой итерации. Наибольшую сложность представляет собой пересчет матрицы, сложность которого &amp;lt;math&amp;gt;O(c^2 nd)&amp;lt;/math&amp;gt; (по сравнению со сложностью &amp;lt;math&amp;gt;O(cnd)&amp;lt;/math&amp;gt; расчета расстояний, вычисления центроидов и проверки условия останова). Итого общая сложность алгоритма &amp;lt;math&amp;gt;O(c^2 ndi)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
Информационный граф представлен на рисунке ниже.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 1, 2, совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз для каждого кластера. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 1&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 2&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m*X_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем вектор размера &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; и матрицу размера &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;. &lt;br /&gt;
Далее совершаем поэлементное сложение векторов и матриц соответственно, а затем делим каждый столбец в матрице на соответствующий элемент в векторе.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй ярус&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 3, 4, 5 также совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 4&#039;&#039;&#039;: обновление значения &amp;lt;math&amp;gt;w_{ij}&amp;lt;/math&amp;gt; по указанной в разделе 1.2 в пункте 5 формуле.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 5&#039;&#039;&#039;: &amp;lt;math&amp;gt;maximum = max(|w_{ij} - w_{ij}^{prev}|, maximum)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 6&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^{prev} = w_{ij}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем число &amp;lt;math&amp;gt;maximum&amp;lt;/math&amp;gt;. Далее находим максимальное значение из полученных величин для каждой ветки. Затем проверяем условие останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:Scheme.JPG]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельная сложность алгоритма: &amp;lt;math&amp;gt;M*c^2*i&amp;lt;/math&amp;gt;. Такая сложность получается за счет распараллеливания на каждом ярусе &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; операций. Иерархическая структура параллелизма подробно описана в [[#Информационный граф|п.1.7]].&lt;br /&gt;
&lt;br /&gt;
В алгоритме не возникает скошенного параллелизма.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Входные данные алгоритма: набор векторов &amp;lt;math&amp;gt;x_i&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i = 1,...,M&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
* Выходные данные алгоритма: матрица вероятностей принадлежности векторов кластерам &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной формы алгоритма: &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;&lt;br /&gt;
* Вычислительная мощность: &amp;lt;math&amp;gt;{dc^2i} \over {c+d}&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Устойчивость: алгоритм не является устойчивым, поэтому существует много исследований о том, как первоначально выбрать параметры кластеризации.&lt;br /&gt;
* Сбалансированность: в данном алгоритме операция умножения доминирует над операцией сложения. Операции между параллельными ветвями сбалансированны.&lt;br /&gt;
* Детерминированность: алгоритм не является детерминированным, так как матрица нечеткого разбиение генерируется произвольно.&lt;br /&gt;
* Степень исхода вершины информационного графа ( для одной интерации): 2 (3 - с учетом, если выходные данные пошли на следующую итерацию).&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма = &lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
==Существующие реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
* Реализация алгоритма на POSTGRESQL: http://num-meth.srcc.msu.ru/zhurnal/tom_2012/pdf/v13r207.pdf&lt;br /&gt;
* Библиотека для MATLAB: http://www.mathworks.com/help/fuzzy/fcm.html (распространяется на коммерческой основе)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=9470</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=9470"/>
		<updated>2016-10-15T12:32:08Z</updated>

		<summary type="html">&lt;p&gt;Yushin: /* Свойства алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(Mdc^2i)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - количество итераций&lt;br /&gt;
| input_data         = &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt;, [количество наблюдений * размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt;, [количество наблюдений * количество кластеров]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;2i&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]], [[Участник:Yushin|Павел Юшин]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;{{Cite journal|last=Dunn|first=J. C.|date=1973-01-01|title=A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters|url=http://dx.doi.org/10.1080/01969727308546046|journal=Journal of Cybernetics|volume=3|issue=3|pages=32–57|doi=10.1080/01969727308546046|issn=0022-0280}}&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - экспоненциальный вес; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма будут отличать менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;0 &amp;lt; \sum_{i = 1}^M w_{ij} &amp;lt; M, j = 1, ..., c&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда алгоритм принимает следующий вид:&lt;br /&gt;
&lt;br /&gt;
1) Задаем параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
2) Генерируем случайным образом матрицу нечеткого разбиения с учетом условий &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3) Рассчитываем центроиды (центры кластеров): &amp;lt;math&amp;gt;V_j = {{\sum_{i=1}^M w_{ij}^m * X_i} \over {\sum_{i=1}^M w_{ij}^m}}, j = 1, ..., c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Рассчитываем расстояния между объектами &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и центроидами:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_{ij} = {||X_i - V_j||}, i = 1,...,M; j = 1,...,c &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5) Пересчет элементов матрицы разбиения:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} &amp;gt;0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = {{1}\over {{ (\sum_{k=1}^c {{D_{ij}}\over{D_{ik}}} ) }^{2/(m-1)}}}, j = 1,...,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} =0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = \delta_{ij}, j = 1,...,c&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\delta_{ij}&amp;lt;/math&amp;gt; - символ Кронекера&lt;br /&gt;
&lt;br /&gt;
6) Если &amp;lt;math&amp;gt;|| F - F^{*} || &amp;lt; \varepsilon &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;F^{*}&amp;lt;/math&amp;gt; - матрица нечеткого разбиения предыдущей итерации, то идем далее, иначе возвращаемся на пункт 3.&lt;br /&gt;
&lt;br /&gt;
7) Конец.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром алгоритма являются пункты (3), (4), (5) - расчет центроидов, вычисление расстояний и пересчет элементов матрицы соответственно&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Основные шаги при реализации алгоритма&lt;br /&gt;
*	Генерация случайной матрицы размера &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на где &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;, проверка условий&lt;br /&gt;
*	Расчет центроидов – по сути, скалярное произведение с нормировкой&lt;br /&gt;
*	Расчет расстояний – в общепринятом случае является скалярным произведением&lt;br /&gt;
*	Пересчет матрицы – по сути, скалярное произведение&lt;br /&gt;
*	Проверка условий останова – вычисление нормы&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
    float ** FuzzyCMeans (float** X, c, m, eps){&lt;br /&gt;
        n = X.size();&lt;br /&gt;
        r = X[0].size();&lt;br /&gt;
        centers = generateZeroFill(c, r)&lt;br /&gt;
        Wprev = genetateRandFill(n, c);&lt;br /&gt;
        W = Wprev;&lt;br /&gt;
        while (true){&lt;br /&gt;
            // обновляем центры кластеров &lt;br /&gt;
            for (int i=0; i&amp;lt;c; i++){&lt;br /&gt;
                float * num = new float []();&lt;br /&gt;
                float den = 0;&lt;br /&gt;
                for (int j=0; j&amp;lt;n; j++){&lt;br /&gt;
                    num += pow(W[j][i], m) * X[j];&lt;br /&gt;
                    den+=pow(W[j][i], m);&lt;br /&gt;
                }&lt;br /&gt;
                centers[i] = num / den;&lt;br /&gt;
            }&lt;br /&gt;
            //обновляем вероятности W и считаем расстояние между матрицами W и Wprev&lt;br /&gt;
            float max_diff = 0;&lt;br /&gt;
            for (int i=0; i&amp;lt;n; i++)&lt;br /&gt;
                for (int j=0; j&amp;lt;c; j++){&lt;br /&gt;
                    total = 0;&lt;br /&gt;
                    for (int m=0; m&amp;lt;с; m++)&lt;br /&gt;
                        total += pow(distance(X[i], centers[j]) / distance(X[i], centers[m]), 2/(m-1));&lt;br /&gt;
                    W[i][j] = 1/total;&lt;br /&gt;
                    max_diff = max(abs(Wprev[i][j]-W[i][j]), max_diff);&lt;br /&gt;
                    Wprev[i][j] = W[i][j];&lt;br /&gt;
               }               &lt;br /&gt;
           if (max_diff &amp;lt; eps):                &lt;br /&gt;
                break;&lt;br /&gt;
        }&lt;br /&gt;
        return W;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Последовательная сложность алгоритма состоит из сложности каждой итерации умноженной на их количество. Так как число итераций заранее неизвестно и зависит от входных параметров, рассмотрим сложность на каждой итерации. Наибольшую сложность представляет собой пересчет матрицы, сложность которого &amp;lt;math&amp;gt;O(c^2 nd)&amp;lt;/math&amp;gt; (по сравнению со сложностью &amp;lt;math&amp;gt;O(cnd)&amp;lt;/math&amp;gt; расчета расстояний, вычисления центроидов и проверки условия останова). Итого общая сложность алгоритма &amp;lt;math&amp;gt;O(c^2 ndi)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
Информационный граф представлен на рисунке ниже.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 1, 2, совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз для каждого кластера. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 1&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 2&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m*X_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем вектор размера &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; и матрицу размера &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;. &lt;br /&gt;
Далее совершаем поэлементное сложение векторов и матриц соответственно, а затем делим каждый столбец в матрице на соответствующий элемент в векторе.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй ярус&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 3, 4, 5 также совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 4&#039;&#039;&#039;: обновление значения &amp;lt;math&amp;gt;w_{ij}&amp;lt;/math&amp;gt; по указанной в разделе 1.2 в пункте 5 формуле.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 5&#039;&#039;&#039;: &amp;lt;math&amp;gt;maximum = max(|w_{ij} - w_{ij}^{prev}|, maximum)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 6&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^{prev} = w_{ij}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем число &amp;lt;math&amp;gt;maximum&amp;lt;/math&amp;gt;. Далее находим максимальное значение из полученных величин для каждой ветки. Затем проверяем условие останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:Scheme.JPG]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Входные данные алгоритма: набор векторов &amp;lt;math&amp;gt;x_i&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i = 1,...,M&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
* Выходные данные алгоритма: матрица вероятностей принадлежности векторов кластерам &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной формы алгоритма: &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;&lt;br /&gt;
* Вычислительная мощность: &amp;lt;math&amp;gt;{dc^2i} \over {c+d}&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Устойчивость: алгоритм не является устойчивым, поэтому существует много исследований о том, как первоначально выбрать параметры кластеризации.&lt;br /&gt;
* Сбалансированность: в данном алгоритме операция умножения доминирует над операцией сложения. Операции между параллельными ветвями сбалансированны.&lt;br /&gt;
* Детерминированность: алгоритм не является детерминированным, так как матрица нечеткого разбиение генерируется произвольно.&lt;br /&gt;
* Степень исхода вершины информационного графа ( для одной интерации): 2 (3 - с учетом, если выходные данные пошли на следующую итерацию).&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма = &lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
==Существующие реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
* Реализация алгоритма на POSTGRESQL: http://num-meth.srcc.msu.ru/zhurnal/tom_2012/pdf/v13r207.pdf&lt;br /&gt;
* Библиотека для MATLAB: http://www.mathworks.com/help/fuzzy/fcm.html (распространяется на коммерческой основе)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=9442</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=9442"/>
		<updated>2016-10-15T12:21:13Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(Mdc^2i)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - количество итераций&lt;br /&gt;
| input_data         = &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt;, [количество наблюдений * размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt;, [количество наблюдений * количество кластеров]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;2i&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]], [[Участник:Yushin|Павел Юшин]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;{{Cite journal|last=Dunn|first=J. C.|date=1973-01-01|title=A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters|url=http://dx.doi.org/10.1080/01969727308546046|journal=Journal of Cybernetics|volume=3|issue=3|pages=32–57|doi=10.1080/01969727308546046|issn=0022-0280}}&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - экспоненциальный вес; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма будут отличать менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;0 &amp;lt; \sum_{i = 1}^M w_{ij} &amp;lt; M, j = 1, ..., c&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда алгоритм принимает следующий вид:&lt;br /&gt;
&lt;br /&gt;
1) Задаем параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
2) Генерируем случайным образом матрицу нечеткого разбиения с учетом условий &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3) Рассчитываем центроиды (центры кластеров): &amp;lt;math&amp;gt;V_j = {{\sum_{i=1}^M w_{ij}^m * X_i} \over {\sum_{i=1}^M w_{ij}^m}}, j = 1, ..., c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Рассчитываем расстояния между объектами &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и центроидами:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_{ij} = {||X_i - V_j||}, i = 1,...,M; j = 1,...,c &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5) Пересчет элементов матрицы разбиения:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} &amp;gt;0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = {{1}\over {{ (\sum_{k=1}^c {{D_{ij}}\over{D_{ik}}} ) }^{2/(m-1)}}}, j = 1,...,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} =0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = \delta_{ij}, j = 1,...,c&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\delta_{ij}&amp;lt;/math&amp;gt; - символ Кронекера&lt;br /&gt;
&lt;br /&gt;
6) Если &amp;lt;math&amp;gt;|| F - F^{*} || &amp;lt; \varepsilon &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;F^{*}&amp;lt;/math&amp;gt; - матрица нечеткого разбиения предыдущей итерации, то идем далее, иначе возвращаемся на пункт 3.&lt;br /&gt;
&lt;br /&gt;
7) Конец.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром алгоритма являются пункты (3), (4), (5) - расчет центроидов, вычисление расстояний и пересчет элементов матрицы соответственно&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Основные шаги при реализации алгоритма&lt;br /&gt;
*	Генерация случайной матрицы размера &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на где &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;, проверка условий&lt;br /&gt;
*	Расчет центроидов – по сути, скалярное произведение с нормировкой&lt;br /&gt;
*	Расчет расстояний – в общепринятом случае является скалярным произведением&lt;br /&gt;
*	Пересчет матрицы – по сути, скалярное произведение&lt;br /&gt;
*	Проверка условий останова – вычисление нормы&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
    float ** FuzzyCMeans (float** X, c, m, eps){&lt;br /&gt;
        n = X.size();&lt;br /&gt;
        r = X[0].size();&lt;br /&gt;
        centers = generateZeroFill(c, r)&lt;br /&gt;
        Wprev = genetateRandFill(n, c);&lt;br /&gt;
        W = Wprev;&lt;br /&gt;
        while (true){&lt;br /&gt;
            // обновляем центры кластеров &lt;br /&gt;
            for (int i=0; i&amp;lt;c; i++){&lt;br /&gt;
                float * num = new float []();&lt;br /&gt;
                float den = 0;&lt;br /&gt;
                for (int j=0; j&amp;lt;n; j++){&lt;br /&gt;
                    num += pow(W[j][i], m) * X[j];&lt;br /&gt;
                    den+=pow(W[j][i], m);&lt;br /&gt;
                }&lt;br /&gt;
                centers[i] = num / den;&lt;br /&gt;
            }&lt;br /&gt;
            //обновляем вероятности W и считаем расстояние между матрицами W и Wprev&lt;br /&gt;
            float max_diff = 0;&lt;br /&gt;
            for (int i=0; i&amp;lt;n; i++)&lt;br /&gt;
                for (int j=0; j&amp;lt;c; j++){&lt;br /&gt;
                    total = 0;&lt;br /&gt;
                    for (int m=0; m&amp;lt;с; m++)&lt;br /&gt;
                        total += pow(distance(X[i], centers[j]) / distance(X[i], centers[m]), 2/(m-1));&lt;br /&gt;
                    W[i][j] = 1/total;&lt;br /&gt;
                    max_diff = max(abs(Wprev[i][j]-W[i][j]), max_diff);&lt;br /&gt;
                    Wprev[i][j] = W[i][j];&lt;br /&gt;
               }               &lt;br /&gt;
           if (max_diff &amp;lt; eps):                &lt;br /&gt;
                break;&lt;br /&gt;
        }&lt;br /&gt;
        return W;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Последовательная сложность алгоритма состоит из сложности каждой итерации умноженной на их количество. Так как число итераций заранее неизвестно и зависит от входных параметров, рассмотрим сложность на каждой итерации. Наибольшую сложность представляет собой пересчет матрицы, сложность которого &amp;lt;math&amp;gt;O(c^2 nd)&amp;lt;/math&amp;gt; (по сравнению со сложностью &amp;lt;math&amp;gt;O(cnd)&amp;lt;/math&amp;gt; расчета расстояний, вычисления центроидов и проверки условия останова). Итого общая сложность алгоритма &amp;lt;math&amp;gt;O(c^2 ndi)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
Информационный граф представлен на рисунке ниже.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 1, 2, совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз для каждого кластера. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 1&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 2&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^m*X_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем вектор размера &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; и матрицу размера &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; x &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;. &lt;br /&gt;
Далее совершаем поэлементное сложение векторов и матриц соответственно, а затем делим каждый столбец в матрице на соответствующий элемент в векторе.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй ярус&#039;&#039;&#039; состоит их &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; параллельных операций 3, 4, 5 также совершаемых в цикле &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; раз.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 4&#039;&#039;&#039;: обновление значения &amp;lt;math&amp;gt;w_{ij}&amp;lt;/math&amp;gt; по указанной в разделе 1.2 в пункте 5 формуле.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 5&#039;&#039;&#039;: &amp;lt;math&amp;gt;maximum = max(|w_{ij} - w_{ij}^{prev}|, maximum)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Операция 6&#039;&#039;&#039;: &amp;lt;math&amp;gt;w_{ij}^{prev} = w_{ij}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; - номер итерации в цикле, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - номер параллельной ветви.&lt;br /&gt;
&lt;br /&gt;
На выходе из каждой ветки получаем число &amp;lt;math&amp;gt;maximum&amp;lt;/math&amp;gt;. Далее находим максимальное значение из полученных величин для каждой ветки. Затем проверяем условие останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:Scheme.JPG]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Входные данные алгоритма: набор векторов &amp;lt;math&amp;gt;x_i&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i = 1,...,M&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
* Выходные данные алгоритма: матрица вероятностей принадлежности векторов кластерам &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной формы алгоритма: &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
* Вычислительная мощность: &amp;lt;math&amp;gt;{dc^2i} \over {c+d}&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Устойчивость: алгоритм не является устойчивым, поэтому существует много исследований о том, как первоначально выбрать параметры кластеризации.&lt;br /&gt;
* Сбалансированность: в данном алгоритме операция умножения доминирует над операцией сложения. Операции между параллельными ветвями сбалансированны.&lt;br /&gt;
* Детерминированность: алгоритм не является детерминированным, так как матрица нечеткого разбиение генерируется произвольно.&lt;br /&gt;
* Степень исхода вершины информационного графа ( для одной интерации): 2 (3 - с учетом, если выходные данные пошли на следующую итерацию).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма = &lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
==Существующие реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
* Реализация алгоритма на POSTGRESQL: http://num-meth.srcc.msu.ru/zhurnal/tom_2012/pdf/v13r207.pdf&lt;br /&gt;
* Библиотека для MATLAB: http://www.mathworks.com/help/fuzzy/fcm.html (распространяется на коммерческой основе)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Lineprinter&amp;diff=9366</id>
		<title>Обсуждение участника:Lineprinter</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Lineprinter&amp;diff=9366"/>
		<updated>2016-10-15T12:00:33Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Перенос ==&lt;br /&gt;
Статья: [[Участники: Бобошко А., Юмакаева А./Решение начальной задачи Коши для системы ОДУ методом Рунге-Кутта 4-го порядка]];&lt;br /&gt;
Выполняют: Бобошко Алексей и Юмакаева Алина&lt;br /&gt;
&lt;br /&gt;
Статья: [[Алгоритм кластеризации, основанный на сетях Кохоннена]];&lt;br /&gt;
Выполняют:  Логвиненко Александра и Адиев Тохтар&lt;br /&gt;
&lt;br /&gt;
Статья: [[Ортогонализация Грама-Шмидта]];&lt;br /&gt;
Выполняют: [[Участник:KibAndrey| Кибанов Андрей]] и Аджиева Татьяна&lt;br /&gt;
&lt;br /&gt;
Статья: [[Самоорганизующиеся карты Кохонена]];&lt;br /&gt;
Выполняет: [[Участник:Anton goy| Гой Антон]]&lt;br /&gt;
&lt;br /&gt;
Статья:[[ЕМ-алгоритм_(Тематическое_моделирование)]];&lt;br /&gt;
Выполняют: Мурат Апишев и Андрей Заночкин&lt;br /&gt;
&lt;br /&gt;
Статья:[[Алгоритм_Ланцоша_с_полной_переортогонализацией]];&lt;br /&gt;
Выполняет:[[Участник:Sfedotov| Федотов С.А.]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Алгоритм_k-средних]]&lt;br /&gt;
Выполняют: [[Участник:Error2407|Богомазов Евгений]], [[Участник:Илья_Егоров|Егоров Илья]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Нечеткий_алгоритм_С_средних]]&lt;br /&gt;
Выполняют: [[Участник:Demon smd|Д.А.Гуськов]], [[Участник:marina abramenkova|М.А.Абраменкова]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Решение_задачи_Коши_для_системы_ОДУ_методом_Рунге-Кутты_4_порядка]];&lt;br /&gt;
Выполняют: [[Участник:Алимов_Дамир_Алиевич|Алимов Дамир]] и [[Участник:Anlesnichiy|Антон Лесничий]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Строгий_алгоритм_С_средних_(Hard_C-Means,_HCM)]];&lt;br /&gt;
Выполняют: [[Участник:Светлана_Лукьяненко|Лукьяненко Светлана]] и [[Участник:Юрий_Комаров|Комаров Юрий]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Алгоритм кластеризации, основанный на минимальном остовном дереве]];&lt;br /&gt;
Выполняет: [[Участник:Astandrik | Стандрик Антон Сергеевич]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Умножение разреженной матрицы на вектор]];&lt;br /&gt;
Выполняет: [[Участник:Lexaloris | Новоселов Алексей]], Выполняет: [[Участник:pahom | Кочетков Павел]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Нахождение_собственных_чисел_квадратной_матрицы_методом_QR_разложения_(3)|Нахождение собственных чисел квадратной матрицы методом QR разложения (3)]];&lt;br /&gt;
Выполняют: [[Участник:Смирнова_Александра|Смирнова А.С.]], [[Участник:Александра_Киямова|Киямова А.]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Метод_Якоби_вычисления_сингулярных_чисел_и_векторов]];&lt;br /&gt;
Выполняют: [[Участница:Почернина_Елена| Почернина Елена]] и [[Участница:Светлана|Костюкова Светлана]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Метод_Ньютона_для_решения_систем_нелинейных_уравнений(2)]];&lt;br /&gt;
Выполняют: [[Участник:Oleggium|Гирняк О.Р.]], [[Участник:Dimx19|Васильков Д.А.]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Алгоритм_кластеризации_с_использованием_представлений]];&lt;br /&gt;
Выполняют: [[Участник:Cookie|Шатков С.А.]], [[Антохина Ю.А.]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Быстрое_преобразование_Фурье_(FFT)|Быстрое преобразование Фурье (FFT)]];&lt;br /&gt;
Выполняют: [[Участник:Victoria_Stepanischeva|Степанищева Виктория]] и [[Участник:Igor_Munkin|Мунькин Игорь]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Быстрое_дискретное_преобразование_Фурье|Быстрое_дискретное_преобразование_Фурье]];&lt;br /&gt;
Выполняют: [[Участник:ivanov.kir.m | К.М.Иванов]], [[Участник:Pumpkin | А.C.Сапин]]&lt;br /&gt;
&lt;br /&gt;
Статья:[[Алгоритм_k_средних]]&lt;br /&gt;
Выполняют: [[Участник:Parkhomenko|Пархоменко Павел]], [[Участник:ivan.mashonskiy|Машонский Иван]]&lt;br /&gt;
&lt;br /&gt;
Статья:[[EM-алгоритм_кластеризации]]&lt;br /&gt;
Выполняет: [[Участник:Noite|Зинченко Дмитрий]]&lt;br /&gt;
&lt;br /&gt;
Статья:[[Алгоритм_k_means]]&lt;br /&gt;
Выполняют: [[Участник:IanaV| Валуйская Яна]], [[Глотов Евгений]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Метод Якоби вычисления собственных значений симметричной матрицы ЗП |Метод Якоби вычисления собственных значений симметричной матрицы ЗП]];&lt;br /&gt;
Выполняют: [[Участник:Зиновьев Владимир|Зиновьев В.С.]], [[Участник:Пронин Андрей|Пронин А.М.]]&lt;br /&gt;
&lt;br /&gt;
Статья:[[Алгоритм_кластеризации,_основанный_на_минимальном_покрывающем_дереве]]&lt;br /&gt;
Выполняет: [[Участник:Kanast74|Дмитриева Анастасия]]&lt;br /&gt;
&lt;br /&gt;
Статья:[[Нахождение_собственных_чисел_квадратной_матрицы_методом_QR_разложения_(4)]]&lt;br /&gt;
Выполняют: [[Участник:F-morozov|Морозов Ф. В.]], [[Участник:Nataliya|Пащенко Н. Ф.]]&lt;br /&gt;
&lt;br /&gt;
Статья:[[Хранение_ненулевых_элементов_разреженных_матриц._Умножение_разреженной_матрицы_на_вектор]];&lt;br /&gt;
Выполняют: [[Участник:Trrufina|Третьякова Р.М.]] и [[Участник:Екатерина_Буторина|Буторина Е.В.]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Алгоритм_кластеризации_с_использованием_представлений2]];&lt;br /&gt;
Выполняет: [[Участник:Лукьянова Анна|Лукьянова А.Я.]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Метод Якоби вычисления собственных значений симметричной матрицы]];&lt;br /&gt;
Выполняют: [[Участник: Galkina|Галкина А.С.]], [[Участник: Игорь|Плахов И.А.]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Метод рекурсивной координатной бисекции]];&lt;br /&gt;
Выполняют: [[Участник: Obirvalger|Гордеев Михаил]], [[Участник: KolmakovEA|Колмаков Евгений]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Итерационный метод решения системы линейных алгебраических уравнений GMRES (обобщенный метод минимальных невязок)]];&lt;br /&gt;
Выполняют: [[Участник: Эльвира Ахиярова|Ахиярова Эльвира]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Хранение ненулевых элементов разреженной матрицы. Умножение разреженной матрицы на вектор]];&lt;br /&gt;
Выполняют: [[Участник: Janyell|Сычева Евгения]], [[Участник: Ahahalin|Хахалин Анатолий]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Построение матрицы Адамара произвольного размера]];&lt;br /&gt;
Выполняют: [[Участник: Бугаков Юрий|Бугаков Юрий]], Кужамалиев Ернур&lt;br /&gt;
&lt;br /&gt;
Статья: [[Вычисление определенного интеграла с использованием адаптивно сгущающейся сетки (1)]]&lt;br /&gt;
Выполняют: [[Участница:Sannikovats| Санникова Татьяна Сергеевна]], [[Участник:Plukshin| Лукшин Петр Андреевич]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Алгоритм кластеризации, основанный на построении каркаса]];&lt;br /&gt;
Выполняют: [[Участник:SenderovichNikita| Сендерович Никита]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Алгоритм кластеризации, основанный на максимизации ожидания]];&lt;br /&gt;
Выполняют: Готман Мария, Лукашкина Юлия&lt;br /&gt;
&lt;br /&gt;
Статья: [[Partitioning_Around_Medoids_(PAM)]]&lt;br /&gt;
Выполняют: [[Участник:Avasilenko|А.Э.Василенко]], [[Участник:Anastasia|А.В.Тузикова]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Нечеткий алгоритм С-средних (Fuzzy C-means)]]&lt;br /&gt;
Выполняют: [[Участник:Nikmedoed|Н.А. Муромцев]], [[Участник:illusive_mike|М.С. Дворецкий]]&lt;br /&gt;
&lt;br /&gt;
Статья: [[Нечеткий алгоритм C средних]]&lt;br /&gt;
Выполняют: [[Участник:Gkhazeeva|Гелана Хазеева]], [[Участник:Yushin|Павел Юшин]]&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=7871</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=7871"/>
		<updated>2016-10-14T17:59:48Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(Mdc^2i)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - количество итераций&lt;br /&gt;
| input_data         = &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt;, [количество наблюдений * размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt;, [количество наблюдений * количество кластеров]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]], [[Участник:Yushin|Павел Юшин]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;{{Cite journal|last=Dunn|first=J. C.|date=1973-01-01|title=A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters|url=http://dx.doi.org/10.1080/01969727308546046|journal=Journal of Cybernetics|volume=3|issue=3|pages=32–57|doi=10.1080/01969727308546046|issn=0022-0280}}&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - экспоненциальный вес; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма будут отличать менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;0 &amp;lt; \sum_{i = 1}^M w_{ij} &amp;lt; M, j = 1, ..., c&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда алгоритм принимает следующий вид:&lt;br /&gt;
&lt;br /&gt;
1) Задаем параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
2) Генерируем случайным образом матрицу нечеткого разбиения с учетом условий &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3) Рассчитываем центроиды (центры кластеров): &amp;lt;math&amp;gt;V_j = {{\sum_{i=1}^M w_{ij}^m * X_i} \over {\sum_{i=1}^M w_{ij}^m}}, j = 1, ..., c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Рассчитываем расстояния между объектами &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и центроидами:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_{ij} = {||X_i - V_j||}, i = 1,...,M; j = 1,...,c &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5) Пересчет элементов матрицы разбиения:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} &amp;gt;0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = {{1}\over {{ (\sum_{k=1}^c {{D_{ij}}\over{D_{ik}}} ) }^{2/(m-1)}}}, j = 1,...,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} =0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = \delta_{ij}, j = 1,...,c&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\delta_{ij}&amp;lt;/math&amp;gt; - символ Кронекера&lt;br /&gt;
&lt;br /&gt;
6) Если &amp;lt;math&amp;gt;|| F - F^{*} || &amp;lt; \varepsilon &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;F^{*}&amp;lt;/math&amp;gt; - матрица нечеткого разбиения предыдущей итерации, то идем далее, иначе возвращаемся на пункт 3.&lt;br /&gt;
&lt;br /&gt;
7) Конец.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром алгоритма являются пункты (3), (4), (5) - расчет центроидов, вычисление расстояний и пересчет элементов матрицы соответственно&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Основные шаги при реализации алгоритма&lt;br /&gt;
*	Генерация случайной матрицы размера &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на где &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;, проверка условий&lt;br /&gt;
*	Расчет центроидов – по сути, скалярное произведение с нормировкой&lt;br /&gt;
*	Расчет расстояний – в общепринятом случае является скалярным произведением&lt;br /&gt;
*	Пересчет матрицы – по сути, скалярное произведение&lt;br /&gt;
*	Проверка условий останова – вычисление нормы&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
    float ** FuzzyCMeans (float** X, c, m, eps){&lt;br /&gt;
        n = X.size();&lt;br /&gt;
        r = X[0].size();&lt;br /&gt;
        centers = generateZeroFill(c, r)&lt;br /&gt;
        Wprev = genetateRandFill(n, c);&lt;br /&gt;
        W = Wprev;&lt;br /&gt;
        while (true){&lt;br /&gt;
            // обновляем центры кластеров &lt;br /&gt;
            for (int i=0; i&amp;lt;c; i++){&lt;br /&gt;
                float * num = new float []();&lt;br /&gt;
                float den = 0;&lt;br /&gt;
                for (int j=0; j&amp;lt;n; j++){&lt;br /&gt;
                    num += pow(W[j][i], m) * X[j];&lt;br /&gt;
                    den+=pow(W[j][i], m);&lt;br /&gt;
                }&lt;br /&gt;
                centers[i] = num / den;&lt;br /&gt;
            }&lt;br /&gt;
            //обновляем вероятности W и считаем расстояние между матрицами W и Wprev&lt;br /&gt;
            float max_diff = 0;&lt;br /&gt;
            for (int i=0; i&amp;lt;n; i++)&lt;br /&gt;
                for (int j=0; j&amp;lt;c; j++){&lt;br /&gt;
                    total = 0;&lt;br /&gt;
                    for (int m=0; m&amp;lt;с; m++)&lt;br /&gt;
                        total += pow(distance(X[i], centers[j]) / distance(X[i], centers[m]), 2/(m-1));&lt;br /&gt;
                    W[i][j] = 1/total;&lt;br /&gt;
                    max_diff = max(abs(Wprev[i][j]-W[i][j]), max_diff);&lt;br /&gt;
                    Wprev[i][j] = W[i][j];&lt;br /&gt;
               }               &lt;br /&gt;
           if (max_diff &amp;lt; eps):                &lt;br /&gt;
                break;&lt;br /&gt;
        }&lt;br /&gt;
        return W;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Последовательная сложность алгоритма состоит из сложности каждой итерации умноженной на их количество. Так как число итераций заранее неизвестно и зависит от входных параметров, рассмотрим сложность на каждой итерации. Наибольшую сложность представляет собой пересчет матрицы, сложность которого &amp;lt;math&amp;gt;O(c^2 nd)&amp;lt;/math&amp;gt; (по сравнению со сложностью &amp;lt;math&amp;gt;O(cnd)&amp;lt;/math&amp;gt; расчета расстояний, вычисления центроидов и проверки условия останова). Итого общая сложность алгоритма &amp;lt;math&amp;gt;O(c^2 ndi)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Входные данные алгоритма: набор векторов &amp;lt;math&amp;gt;x_i&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i = 1,...,M&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
* Выходные данные алгоритма: матрица вероятностей принадлежности векторов кластерам &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной формы алгоритма: &amp;lt;math&amp;gt;{xz} \over {xz}&amp;lt;/math&amp;gt;&lt;br /&gt;
* Вычислительная мощность: &amp;lt;math&amp;gt;{dc^2i} \over {c+d}&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Устойчивость: алгоритм не является устойчивым, поэтому существует много исследований о том, как первоначально выбрать параметры кластеризации.&lt;br /&gt;
* Сбалансированность: в данном алгоритме операция умножения доминирует над операцией сложения. Операции между параллельными ветвями сбалансированны.&lt;br /&gt;
* Детерминированность: алгоритм не является детерминированным, так как матрица нечеткого разбиение генерируется произвольно.&lt;br /&gt;
* Степень исхода вершины информационного графа ( для одной интерации): 2 (3 - с учетом, если выходные данные пошли на следующую итерацию).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма = &lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
==Существующие реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
* Реализация алгоритма на POSTGRESQL: http://num-meth.srcc.msu.ru/zhurnal/tom_2012/pdf/v13r207.pdf&lt;br /&gt;
* Библиотека для MATLAB: http://www.mathworks.com/help/fuzzy/fcm.html (распространяется на коммерческой основе)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=7863</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=7863"/>
		<updated>2016-10-14T17:55:32Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(Mdc^2i)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - количество итераций&lt;br /&gt;
| input_data         = &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt;, [количество наблюдений * размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt;, [количество наблюдений * количество кластеров]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]], [[Участник:Yushin|Павел Юшин]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;{{Cite journal|last=Dunn|first=J. C.|date=1973-01-01|title=A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters|url=http://dx.doi.org/10.1080/01969727308546046|journal=Journal of Cybernetics|volume=3|issue=3|pages=32–57|doi=10.1080/01969727308546046|issn=0022-0280}}&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - экспоненциальный вес; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма будут отличать менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;0 &amp;lt; \sum_{i = 1}^M w_{ij} &amp;lt; M, j = 1, ..., c&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда алгоритм принимает следующий вид:&lt;br /&gt;
&lt;br /&gt;
1) Задаем параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
2) Генерируем случайным образом матрицу нечеткого разбиения с учетом условий &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3) Рассчитываем центроиды (центры кластеров): &amp;lt;math&amp;gt;V_j = {{\sum_{i=1}^M w_{ij}^m * X_i} \over {\sum_{i=1}^M w_{ij}^m}}, j = 1, ..., c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Рассчитываем расстояния между объектами &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и центроидами:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_{ij} = {||X_i - V_j||}, i = 1,...,M; j = 1,...,c &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5) Пересчет элементов матрицы разбиения:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} &amp;gt;0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = {{1}\over {{ (\sum_{k=1}^c {{D_{ij}}\over{D_{ik}}} ) }^{2/(m-1)}}}, j = 1,...,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} =0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = \delta_{ij}, j = 1,...,c&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\delta_{ij}&amp;lt;/math&amp;gt; - символ Кронекера&lt;br /&gt;
&lt;br /&gt;
6) Если &amp;lt;math&amp;gt;|| F - F^{*} || &amp;lt; \varepsilon &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;F^{*}&amp;lt;/math&amp;gt; - матрица нечеткого разбиения предыдущей итерации, то идем далее, иначе возвращаемся на пункт 3.&lt;br /&gt;
&lt;br /&gt;
7) Конец.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром алгоритма являются пункты (3), (4), (5) - расчет центроидов, вычисление расстояний и пересчет элементов матрицы соответственно&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Основные шаги при реализации алгоритма&lt;br /&gt;
*	Генерация случайной матрицы размера &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на где &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;, проверка условий&lt;br /&gt;
*	Расчет центроидов – по сути, скалярное произведение с нормировкой&lt;br /&gt;
*	Расчет расстояний – в общепринятом случае является скалярным произведением&lt;br /&gt;
*	Пересчет матрицы – по сути, скалярное произведение&lt;br /&gt;
*	Проверка условий останова – вычисление нормы&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
    float ** FuzzyCMeans (float** X, c, m, eps){&lt;br /&gt;
        n = X.size();&lt;br /&gt;
        r = X[0].size();&lt;br /&gt;
        centers = generateZeroFill(c, r)&lt;br /&gt;
        Wprev = genetateRandFill(n, c);&lt;br /&gt;
        W = Wprev;&lt;br /&gt;
        while (true){&lt;br /&gt;
            // обновляем центры кластеров &lt;br /&gt;
            for (int i=0; i&amp;lt;c; i++){&lt;br /&gt;
                float * num = new float []();&lt;br /&gt;
                float den = 0;&lt;br /&gt;
                for (int j=0; j&amp;lt;n; j++){&lt;br /&gt;
                    num += pow(W[j][i], m) * X[j];&lt;br /&gt;
                    den+=pow(W[j][i], m);&lt;br /&gt;
                }&lt;br /&gt;
                centers[i] = num / den;&lt;br /&gt;
            }&lt;br /&gt;
            //обновляем вероятности W и считаем расстояние между матрицами W и Wprev&lt;br /&gt;
            float max_diff = 0;&lt;br /&gt;
            for (int i=0; i&amp;lt;n; i++)&lt;br /&gt;
                for (int j=0; j&amp;lt;c; j++){&lt;br /&gt;
                    total = 0;&lt;br /&gt;
                    for (int m=0; m&amp;lt;с; m++)&lt;br /&gt;
                        total += pow(distance(X[i], centers[j]) / distance(X[i], centers[m]), 2/(m-1));&lt;br /&gt;
                    W[i][j] = 1/total;&lt;br /&gt;
                    max_diff = max(abs(Wprev[i][j]-W[i][j]), max_diff);&lt;br /&gt;
                    Wprev[i][j] = W[i][j];&lt;br /&gt;
               }               &lt;br /&gt;
           if (max_diff &amp;lt; eps):                &lt;br /&gt;
                break;&lt;br /&gt;
        }&lt;br /&gt;
        return W;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Последовательная сложность алгоритма состоит из сложности каждой итерации умноженной на их количество. Так как число итераций заранее неизвестно и зависит от входных параметров, рассмотрим сложность на каждой итерации. Наибольшую сложность представляет собой пересчет матрицы, сложность которого &amp;lt;math&amp;gt;O(c^2 nd)&amp;lt;/math&amp;gt; (по сравнению со сложностью &amp;lt;math&amp;gt;O(cnd)&amp;lt;/math&amp;gt; расчета расстояний, вычисления центроидов и проверки условия останова). Итого общая сложность алгоритма &amp;lt;math&amp;gt;O(c^2 ndi)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Входные данные алгоритма: набор векторов &amp;lt;math&amp;gt;x_i&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i = 1,...,M&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
* Выходные данные алгоритма: матрица вероятностей принадлежности векторов кластерам &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной формы алгоритма: &amp;lt;math&amp;gt;{xz} \over {xz}&amp;lt;/math&amp;gt;&lt;br /&gt;
* Вычислительная мощность: &amp;lt;math&amp;gt;{dc^2i} \over {c+d}&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Устойчивость: алгоритм не является устойчивым, поэтому существует много исследований о том, как первоначально выбрать параметры кластеризации.&lt;br /&gt;
* Сбалансированность: в данном алгоритме операция умножения доминирует над операцией сложения. Операции между параллельными ветвями сбалансированны.&lt;br /&gt;
* Детерминированность: алгоритм не является детерминированным, так как матрица нечеткого разбиение генерируется произвольно.&lt;br /&gt;
* Степень исхода вершины информационного графа ( для одной интерации): 2 (3 - с учетом, если выходные данные пошли на следующую итерацию).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма = &lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
==Существующие реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
* Реализация алгоритма на POSTGRESQL: http://num-meth.srcc.msu.ru/zhurnal/tom_2012/pdf/v13r207.pdf&lt;br /&gt;
* Библиотека для MATLAB: http://www.mathworks.com/help/fuzzy/fcm.html (распространяется на коммерческой основе)&lt;br /&gt;
* Библиотека для Python: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=7826</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=7826"/>
		<updated>2016-10-14T17:35:03Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(Mdc^2i)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - количество итераций&lt;br /&gt;
| input_data         = &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt;, [количество наблюдений * размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt;, [количество наблюдений * количество кластеров]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]], [[Участник:Yushin|Павел Юшин]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;{{Cite journal|last=Dunn|first=J. C.|date=1973-01-01|title=A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters|url=http://dx.doi.org/10.1080/01969727308546046|journal=Journal of Cybernetics|volume=3|issue=3|pages=32–57|doi=10.1080/01969727308546046|issn=0022-0280}}&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - экспоненциальный вес; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма будут отличать менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;0 &amp;lt; \sum_{i = 1}^M w_{ij} &amp;lt; M, j = 1, ..., c&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда алгоритм принимает следующий вид:&lt;br /&gt;
&lt;br /&gt;
1) Задаем параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
2) Генерируем случайным образом матрицу нечеткого разбиения с учетом условий &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3) Рассчитываем центроиды (центры кластеров): &amp;lt;math&amp;gt;V_j = {{\sum_{i=1}^M w_{ij}^m * X_i} \over {\sum_{i=1}^M w_{ij}^m}}, j = 1, ..., c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Рассчитываем расстояния между объектами &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и центроидами:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_{ij} = {||X_i - V_j||}, i = 1,...,M; j = 1,...,c &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5) Пересчет элементов матрицы разбиения:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} &amp;gt;0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = {{1}\over {{ (\sum_{k=1}^c {{D_{ij}}\over{D_{ik}}} ) }^{2/(m-1)}}}, j = 1,...,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} =0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = \delta_{ij}, j = 1,...,c&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\delta_{ij}&amp;lt;/math&amp;gt; - символ Кронекера&lt;br /&gt;
&lt;br /&gt;
6) Если &amp;lt;math&amp;gt;|| F - F^{*} || &amp;lt; \varepsilon &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;F^{*}&amp;lt;/math&amp;gt; - матрица нечеткого разбиения предыдущей итерации, то идем далее, иначе возвращаемся на пункт 3.&lt;br /&gt;
&lt;br /&gt;
7) Конец.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром алгоритма являются пункты (3), (4), (5) - расчет центроидов, вычисление расстояний и пересчет элементов матрицы соответственно&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Основные шаги при реализации алгоритма&lt;br /&gt;
*	Генерация случайной матрицы размера &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на где &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;, проверка условий&lt;br /&gt;
*	Расчет центроидов – по сути, скалярное произведение с нормировкой&lt;br /&gt;
*	Расчет расстояний – в общепринятом случае является скалярным произведением&lt;br /&gt;
*	Пересчет матрицы – по сути, скалярное произведение&lt;br /&gt;
*	Проверка условий останова – вычисление нормы&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
    float ** FuzzyCMeans (float** X, c, m, eps){&lt;br /&gt;
        n = X.size();&lt;br /&gt;
        r = X[0].size();&lt;br /&gt;
        centers = generateZeroFill(c, r)&lt;br /&gt;
        Wprev = genetateRandFill(n, c);&lt;br /&gt;
        W = Wprev;&lt;br /&gt;
        while (true){&lt;br /&gt;
            // обновляем центры кластеров &lt;br /&gt;
            for (int i=0; i&amp;lt;c; i++){&lt;br /&gt;
                float * num = new float []();&lt;br /&gt;
                float den = 0;&lt;br /&gt;
                for (int j=0; j&amp;lt;n; j++){&lt;br /&gt;
                    num += pow(W[j][i], m) * X[j];&lt;br /&gt;
                    den+=pow(W[j][i], m);&lt;br /&gt;
                }&lt;br /&gt;
                centers[i] = num / den;&lt;br /&gt;
            }&lt;br /&gt;
            //обновляем вероятности W и считаем расстояние между матрицами W и Wprev&lt;br /&gt;
            float max_diff = 0;&lt;br /&gt;
            for (int i=0; i&amp;lt;n; i++)&lt;br /&gt;
                for (int j=0; j&amp;lt;c; j++){&lt;br /&gt;
                    total = 0;&lt;br /&gt;
                    for (int m=0; m&amp;lt;с; m++)&lt;br /&gt;
                        total += pow(distance(X[i], centers[j]) / distance(X[i], centers[m]), 2/(m-1));&lt;br /&gt;
                    W[i][j] = 1/total;&lt;br /&gt;
                    max_diff = max(abs(Wprev[i][j]-W[i][j]), max_diff);&lt;br /&gt;
                    Wprev[i][j] = W[i][j];&lt;br /&gt;
               }               &lt;br /&gt;
           if (max_diff &amp;lt; eps):                &lt;br /&gt;
                break;&lt;br /&gt;
        }&lt;br /&gt;
        return W;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Последовательная сложность алгоритма состоит из сложности каждой итерации умноженной на их количество. Так как число итераций заранее неизвестно и зависит от входных параметров, рассмотрим сложность на каждой итерации. Наибольшую сложность представляет собой пересчет матрицы, сложность которого &amp;lt;math&amp;gt;O(c^2 nd)&amp;lt;/math&amp;gt; (по сравнению со сложностью &amp;lt;math&amp;gt;O(cnd)&amp;lt;/math&amp;gt; расчета расстояний, вычисления центроидов и проверки условия останова). Итого общая сложность алгоритма &amp;lt;math&amp;gt;O(c^2 ndi)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Входные данные алгоритма: набор векторов &amp;lt;math&amp;gt;x_i&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i = 1,...,M&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
* Выходные данные алгоритма: матрица вероятностей принадлежности векторов кластерам &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной формы алгоритма: &amp;lt;math&amp;gt;{xz} \over {xz}&amp;lt;/math&amp;gt;&lt;br /&gt;
* Вычислительная мощность: &amp;lt;math&amp;gt;{dc^2i} \over {c+d}&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Устойчивость: алгоритм не является устойчивым, поэтому существует много исследований о том, как первоначально выбрать параметры кластеризации.&lt;br /&gt;
* Сбалансированность: в данном алгоритме операция умножения доминирует над операцией сложения. Операции между параллельными ветвями сбалансированны.&lt;br /&gt;
* Детерминированность: алгоритм не является детерминированным, так как матрица нечеткого разбиение генерируется произвольно.&lt;br /&gt;
* Степень исхода вершины информационного графа ( для одной интерации): 2 (3 - с учетом, если выходные данные пошли на следующую итерацию).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма = &lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
==Существующие реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=7796</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=7796"/>
		<updated>2016-10-14T17:06:30Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(Mdc^2i)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - количество итераций&lt;br /&gt;
| input_data         = &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt;, [количество наблюдений * размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt;, [количество наблюдений * количество кластеров]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]], [[Участник:Yushin|Павел Юшин]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;{{Cite journal|last=Dunn|first=J. C.|date=1973-01-01|title=A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters|url=http://dx.doi.org/10.1080/01969727308546046|journal=Journal of Cybernetics|volume=3|issue=3|pages=32–57|doi=10.1080/01969727308546046|issn=0022-0280}}&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - экспоненциальный вес; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма будут отличать менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;0 &amp;lt; \sum_{i = 1}^M w_{ij} &amp;lt; M, j = 1, ..., c&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда алгоритм принимает следующий вид:&lt;br /&gt;
&lt;br /&gt;
1) Задаем параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
2) Генерируем случайным образом матрицу нечеткого разбиения с учетом условий &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3) Рассчитываем центроиды (центры кластеров): &amp;lt;math&amp;gt;V_j = {{\sum_{i=1}^M w_{ij}^m * X_i} \over {\sum_{i=1}^M w_{ij}^m}}, j = 1, ..., c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Рассчитываем расстояния между объектами &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и центроидами:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_{ij} = {||X_i - V_j||}, i = 1,...,M; j = 1,...,c &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5) Пересчет элементов матрицы разбиения:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} &amp;gt;0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = {{1}\over {{ (\sum_{k=1}^c {{D_{ij}}\over{D_{ik}}} ) }^{2/(m-1)}}}, j = 1,...,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} =0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = \delta_{ij}, j = 1,...,c&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\delta_{ij}&amp;lt;/math&amp;gt; - символ Кронекера&lt;br /&gt;
&lt;br /&gt;
6) Если &amp;lt;math&amp;gt;|| F - F^{*} || &amp;lt; \varepsilon &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;F^{*}&amp;lt;/math&amp;gt; - матрица нечеткого разбиения предыдущей итерации, то идем далее, иначе возвращаемся на пункт 3.&lt;br /&gt;
&lt;br /&gt;
7) Конец.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром алгоритма являются пункты (3), (4), (5) - расчет центроидов, вычисление расстояний и пересчет элементов матрицы соответственно&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Основные шаги при реализации алгоритма&lt;br /&gt;
*	Генерация случайной матрицы размера &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на где &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;, проверка условий&lt;br /&gt;
*	Расчет центроидов – по сути, скалярное произведение с нормировкой&lt;br /&gt;
*	Расчет расстояний – в общепринятом случае является скалярным произведением&lt;br /&gt;
*	Пересчет матрицы – по сути, скалярное произведение&lt;br /&gt;
*	Проверка условий останова – вычисление нормы&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
    float ** FuzzyCMeans (float** X, c, m, eps){&lt;br /&gt;
        n = X.size();&lt;br /&gt;
        r = X[0].size();&lt;br /&gt;
        centers = generateZeroFill(c, r)&lt;br /&gt;
        Wprev = genetateRandFill(n, c);&lt;br /&gt;
        W = Wprev;&lt;br /&gt;
        while (true){&lt;br /&gt;
            // обновляем центры кластеров &lt;br /&gt;
            for (int i=0; i&amp;lt;c; i++){&lt;br /&gt;
                float * num = new float []();&lt;br /&gt;
                float den = 0;&lt;br /&gt;
                for (int j=0; j&amp;lt;n; j++){&lt;br /&gt;
                    num += pow(W[j][i], m) * X[j];&lt;br /&gt;
                    den+=pow(W[j][i], m);&lt;br /&gt;
                }&lt;br /&gt;
                centers[i] = num / den;&lt;br /&gt;
            }&lt;br /&gt;
            //обновляем вероятности W и считаем расстояние между матрицами W и Wprev&lt;br /&gt;
            float max_diff = 0;&lt;br /&gt;
            for (int i=0; i&amp;lt;n; i++)&lt;br /&gt;
                for (int j=0; j&amp;lt;c; j++){&lt;br /&gt;
                    total = 0;&lt;br /&gt;
                    for (int m=0; m&amp;lt;с; m++)&lt;br /&gt;
                        total += pow(distance(X[i], centers[j]) / distance(X[i], centers[m]), 2/(m-1));&lt;br /&gt;
                    W[i][j] = 1/total;&lt;br /&gt;
                    max_diff = max(abs(Wprev[i][j]-W[i][j]), max_diff);&lt;br /&gt;
                    Wprev[i][j] = W[i][j];&lt;br /&gt;
               }               &lt;br /&gt;
           if (max_diff &amp;lt; eps):                &lt;br /&gt;
                break;&lt;br /&gt;
        }&lt;br /&gt;
        return W;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Последовательная сложность алгоритма состоит из сложности каждой итерации умноженной на их количество. Так как число итераций заранее неизвестно и зависит от входных параметров, рассмотрим сложность на каждой итерации. Наибольшую сложность представляет собой пересчет матрицы, сложность которого &amp;lt;math&amp;gt;O(c^2 nd)&amp;lt;/math&amp;gt; (по сравнению со сложностью &amp;lt;math&amp;gt;O(cnd)&amp;lt;/math&amp;gt; расчета расстояний, вычисления центроидов и проверки условия останова). Итого общая сложность алгоритма &amp;lt;math&amp;gt;O(c^2 ndi)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Входные данные алгоритма: набор векторов &amp;lt;math&amp;gt;x_i&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i = 1,...,M&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
* Выходные данные алгоритма: матрица вероятностей принадлежности векторов кластерам &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
==Существующие реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=7789</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=7789"/>
		<updated>2016-10-14T17:05:24Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(Mdc^2i)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - количество итераций&lt;br /&gt;
| input_data         = &amp;lt;math&amp;gt;M*d&amp;lt;/math&amp;gt;, [количество наблюдений * размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;M*c&amp;lt;/math&amp;gt;, [количество наблюдений * количество кластеров]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]], [[Участник:Yushin|Павел Юшин]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;{{Cite journal|last=Dunn|first=J. C.|date=1973-01-01|title=A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters|url=http://dx.doi.org/10.1080/01969727308546046|journal=Journal of Cybernetics|volume=3|issue=3|pages=32–57|doi=10.1080/01969727308546046|issn=0022-0280}}&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - экспоненциальный вес; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма будут отличать менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;0 &amp;lt; \sum_{i = 1}^M w_{ij} &amp;lt; M, j = 1, ..., c&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда алгоритм принимает следующий вид:&lt;br /&gt;
&lt;br /&gt;
1) Задаем параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
2) Генерируем случайным образом матрицу нечеткого разбиения с учетом условий &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3) Рассчитываем центроиды (центры кластеров): &amp;lt;math&amp;gt;V_j = {{\sum_{i=1}^M w_{ij}^m * X_i} \over {\sum_{i=1}^M w_{ij}^m}}, j = 1, ..., c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Рассчитываем расстояния между объектами &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и центроидами:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_{ij} = {||X_i - V_j||}, i = 1,...,M; j = 1,...,c &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5) Пересчет элементов матрицы разбиения:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} &amp;gt;0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = {{1}\over {{ (\sum_{k=1}^c {{D_{ij}}\over{D_{ik}}} ) }^{2/(m-1)}}}, j = 1,...,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} =0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = \delta_{ij}, j = 1,...,c&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\delta_{ij}&amp;lt;/math&amp;gt; - символ Кронекера&lt;br /&gt;
&lt;br /&gt;
6) Если &amp;lt;math&amp;gt;|| F - F^{*} || &amp;lt; \varepsilon &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;F^{*}&amp;lt;/math&amp;gt; - матрица нечеткого разбиения предыдущей итерации, то идем далее, иначе возвращаемся на пункт 3.&lt;br /&gt;
&lt;br /&gt;
7) Конец.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром алгоритма являются пункты (3), (4), (5) - расчет центроидов, вычисление расстояний и пересчет элементов матрицы соответственно&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Основные шаги при реализации алгоритма&lt;br /&gt;
*	Генерация случайной матрицы размера &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на где &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;, проверка условий&lt;br /&gt;
*	Расчет центроидов – по сути, скалярное произведение с нормировкой&lt;br /&gt;
*	Расчет расстояний – в общепринятом случае является скалярным произведением&lt;br /&gt;
*	Пересчет матрицы – по сути, скалярное произведение&lt;br /&gt;
*	Проверка условий останова – вычисление нормы&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
    float ** FuzzyCMeans (float** X, c, m, eps){&lt;br /&gt;
        n = X.size();&lt;br /&gt;
        r = X[0].size();&lt;br /&gt;
        centers = generateZeroFill(c, r)&lt;br /&gt;
        Wprev = genetateRandFill(n, c);&lt;br /&gt;
        W = Wprev;&lt;br /&gt;
        while (true){&lt;br /&gt;
            // обновляем центры кластеров &lt;br /&gt;
            for (int i=0; i&amp;lt;c; i++){&lt;br /&gt;
                float * num = new float []();&lt;br /&gt;
                float den = 0;&lt;br /&gt;
                for (int j=0; j&amp;lt;n; j++){&lt;br /&gt;
                    num += pow(W[j][i], m) * X[j];&lt;br /&gt;
                    den+=pow(W[j][i], m);&lt;br /&gt;
                }&lt;br /&gt;
                centers[i] = num / den;&lt;br /&gt;
            }&lt;br /&gt;
            //обновляем вероятности W и считаем расстояние между матрицами W и Wprev&lt;br /&gt;
            float max_diff = 0;&lt;br /&gt;
            for (int i=0; i&amp;lt;n; i++)&lt;br /&gt;
                for (int j=0; j&amp;lt;c; j++){&lt;br /&gt;
                    total = 0;&lt;br /&gt;
                    for (int m=0; m&amp;lt;с; m++)&lt;br /&gt;
                        total += pow(distance(X[i], centers[j]) / distance(X[i], centers[m]), 2/(m-1));&lt;br /&gt;
                    W[i][j] = 1/total;&lt;br /&gt;
                    max_diff = max(abs(Wprev[i][j]-W[i][j]), max_diff);&lt;br /&gt;
                    Wprev[i][j] = W[i][j];&lt;br /&gt;
               }               &lt;br /&gt;
           if (max_diff &amp;lt; eps):                &lt;br /&gt;
                break;&lt;br /&gt;
        }&lt;br /&gt;
        return W;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Последовательная сложность алгоритма состоит из сложности каждой итерации умноженной на их количество. Так как число итераций заранее неизвестно и зависит от входных параметров, рассмотрим сложность на каждой итерации. Наибольшую сложность представляет собой пересчет матрицы, сложность которого &amp;lt;math&amp;gt;O(c^2 nd)&amp;lt;/math&amp;gt; (по сравнению со сложностью &amp;lt;math&amp;gt;O(cnd)&amp;lt;/math&amp;gt; расчета расстояний, вычисления центроидов и проверки условия останова). Итого общая сложность алгоритма &amp;lt;math&amp;gt;O(c^2 ndi)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Входные данные алгоритма: набор векторов &amp;lt;math&amp;gt;x_i&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i = 1,...,M&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
* Выходные данные алгоритма: матрица размерности &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
==Существующие реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=7787</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=7787"/>
		<updated>2016-10-14T17:05:07Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(ndc^2i)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - количество итераций&lt;br /&gt;
| input_data         = &amp;lt;math&amp;gt;n*d&amp;lt;/math&amp;gt;, [количество наблюдений * размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;n*c&amp;lt;/math&amp;gt;, [количество наблюдений * количество кластеров]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]], [[Участник:Yushin|Павел Юшин]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;{{Cite journal|last=Dunn|first=J. C.|date=1973-01-01|title=A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters|url=http://dx.doi.org/10.1080/01969727308546046|journal=Journal of Cybernetics|volume=3|issue=3|pages=32–57|doi=10.1080/01969727308546046|issn=0022-0280}}&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - экспоненциальный вес; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма будут отличать менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;0 &amp;lt; \sum_{i = 1}^M w_{ij} &amp;lt; M, j = 1, ..., c&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда алгоритм принимает следующий вид:&lt;br /&gt;
&lt;br /&gt;
1) Задаем параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
2) Генерируем случайным образом матрицу нечеткого разбиения с учетом условий &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3) Рассчитываем центроиды (центры кластеров): &amp;lt;math&amp;gt;V_j = {{\sum_{i=1}^M w_{ij}^m * X_i} \over {\sum_{i=1}^M w_{ij}^m}}, j = 1, ..., c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Рассчитываем расстояния между объектами &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и центроидами:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_{ij} = {||X_i - V_j||}, i = 1,...,M; j = 1,...,c &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5) Пересчет элементов матрицы разбиения:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} &amp;gt;0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = {{1}\over {{ (\sum_{k=1}^c {{D_{ij}}\over{D_{ik}}} ) }^{2/(m-1)}}}, j = 1,...,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} =0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = \delta_{ij}, j = 1,...,c&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\delta_{ij}&amp;lt;/math&amp;gt; - символ Кронекера&lt;br /&gt;
&lt;br /&gt;
6) Если &amp;lt;math&amp;gt;|| F - F^{*} || &amp;lt; \varepsilon &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;F^{*}&amp;lt;/math&amp;gt; - матрица нечеткого разбиения предыдущей итерации, то идем далее, иначе возвращаемся на пункт 3.&lt;br /&gt;
&lt;br /&gt;
7) Конец.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром алгоритма являются пункты (3), (4), (5) - расчет центроидов, вычисление расстояний и пересчет элементов матрицы соответственно&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Основные шаги при реализации алгоритма&lt;br /&gt;
*	Генерация случайной матрицы размера &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на где &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;, проверка условий&lt;br /&gt;
*	Расчет центроидов – по сути, скалярное произведение с нормировкой&lt;br /&gt;
*	Расчет расстояний – в общепринятом случае является скалярным произведением&lt;br /&gt;
*	Пересчет матрицы – по сути, скалярное произведение&lt;br /&gt;
*	Проверка условий останова – вычисление нормы&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
    float ** FuzzyCMeans (float** X, c, m, eps){&lt;br /&gt;
        n = X.size();&lt;br /&gt;
        r = X[0].size();&lt;br /&gt;
        centers = generateZeroFill(c, r)&lt;br /&gt;
        Wprev = genetateRandFill(n, c);&lt;br /&gt;
        W = Wprev;&lt;br /&gt;
        while (true){&lt;br /&gt;
            // обновляем центры кластеров &lt;br /&gt;
            for (int i=0; i&amp;lt;c; i++){&lt;br /&gt;
                float * num = new float []();&lt;br /&gt;
                float den = 0;&lt;br /&gt;
                for (int j=0; j&amp;lt;n; j++){&lt;br /&gt;
                    num += pow(W[j][i], m) * X[j];&lt;br /&gt;
                    den+=pow(W[j][i], m);&lt;br /&gt;
                }&lt;br /&gt;
                centers[i] = num / den;&lt;br /&gt;
            }&lt;br /&gt;
            //обновляем вероятности W и считаем расстояние между матрицами W и Wprev&lt;br /&gt;
            float max_diff = 0;&lt;br /&gt;
            for (int i=0; i&amp;lt;n; i++)&lt;br /&gt;
                for (int j=0; j&amp;lt;c; j++){&lt;br /&gt;
                    total = 0;&lt;br /&gt;
                    for (int m=0; m&amp;lt;с; m++)&lt;br /&gt;
                        total += pow(distance(X[i], centers[j]) / distance(X[i], centers[m]), 2/(m-1));&lt;br /&gt;
                    W[i][j] = 1/total;&lt;br /&gt;
                    max_diff = max(abs(Wprev[i][j]-W[i][j]), max_diff);&lt;br /&gt;
                    Wprev[i][j] = W[i][j];&lt;br /&gt;
               }               &lt;br /&gt;
           if (max_diff &amp;lt; eps):                &lt;br /&gt;
                break;&lt;br /&gt;
        }&lt;br /&gt;
        return W;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Последовательная сложность алгоритма состоит из сложности каждой итерации умноженной на их количество. Так как число итераций заранее неизвестно и зависит от входных параметров, рассмотрим сложность на каждой итерации. Наибольшую сложность представляет собой пересчет матрицы, сложность которого &amp;lt;math&amp;gt;O(c^2 nd)&amp;lt;/math&amp;gt; (по сравнению со сложностью &amp;lt;math&amp;gt;O(cnd)&amp;lt;/math&amp;gt; расчета расстояний, вычисления центроидов и проверки условия останова). Итого общая сложность алгоритма &amp;lt;math&amp;gt;O(c^2 ndi)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Входные данные алгоритма: набор векторов &amp;lt;math&amp;gt;x_i&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i = 1,...,M&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
* Выходные данные алгоритма: матрица размерности &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
==Существующие реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=7785</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=7785"/>
		<updated>2016-10-14T17:03:43Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(ndc^2i)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - количество итераций&lt;br /&gt;
| input_data         = &amp;lt;math&amp;gt;n*d&amp;lt;/math&amp;gt;, [количество наблюдений * размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;n*c&amp;lt;/math&amp;gt;, [количество наблюдений * количество кластеров]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]], [[Участник:Yushin|Павел Юшин]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;{{Cite journal|last=Dunn|first=J. C.|date=1973-01-01|title=A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters|url=http://dx.doi.org/10.1080/01969727308546046|journal=Journal of Cybernetics|volume=3|issue=3|pages=32–57|doi=10.1080/01969727308546046|issn=0022-0280}}&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - экспоненциальный вес; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма будут отличать менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;0 &amp;lt; \sum_{i = 1}^M w_{ij} &amp;lt; M, j = 1, ..., c&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда алгоритм принимает следующий вид:&lt;br /&gt;
&lt;br /&gt;
1) Задаем параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
2) Генерируем случайным образом матрицу нечеткого разбиения с учетом условий &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3) Рассчитываем центроиды (центры кластеров): &amp;lt;math&amp;gt;V_j = {{\sum_{i=1}^M w_{ij}^m * X_i} \over {\sum_{i=1}^M w_{ij}^m}}, j = 1, ..., c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Рассчитываем расстояния между объектами &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и центроидами:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_{ij} = {||X_i - V_j||}, i = 1,...,M; j = 1,...,c &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5) Пересчет элементов матрицы разбиения:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} &amp;gt;0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = {{1}\over {{ (\sum_{k=1}^c {{D_{ij}}\over{D_{ik}}} ) }^{2/(m-1)}}}, j = 1,...,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} =0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = \delta_{ij}, j = 1,...,c&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\delta_{ij}&amp;lt;/math&amp;gt; - символ Кронекера&lt;br /&gt;
&lt;br /&gt;
6) Если &amp;lt;math&amp;gt;|| F - F^{*} || &amp;lt; \varepsilon &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;F^{*}&amp;lt;/math&amp;gt; - матрица нечеткого разбиения предыдущей итерации, то идем далее, иначе возвращаемся на пункт 3.&lt;br /&gt;
&lt;br /&gt;
7) Конец.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром алгоритма являются пункты (3), (4), (5) - расчет центроидов, вычисление расстояний и пересчет элементов матрицы соответственно&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Основные шаги при реализации алгоритма&lt;br /&gt;
*	Генерация случайной матрицы размера &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на где &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;, проверка условий&lt;br /&gt;
*	Расчет центроидов – по сути, скалярное произведение с нормировкой&lt;br /&gt;
*	Расчет расстояний – в общепринятом случае является скалярным произведением&lt;br /&gt;
*	Пересчет матрицы – по сути, скалярное произведение&lt;br /&gt;
*	Проверка условий останова – вычисление нормы&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
    float ** FuzzyCMeans (float** X, c, m, eps){&lt;br /&gt;
        n = X.size();&lt;br /&gt;
        r = X[0].size();&lt;br /&gt;
        centers = generateZeroFill(c, r)&lt;br /&gt;
        Wprev = genetateRandFill(n, c);&lt;br /&gt;
        W = Wprev;&lt;br /&gt;
        while (true){&lt;br /&gt;
            // обновляем центры кластеров &lt;br /&gt;
            for (int i=0; i&amp;lt;c; i++){&lt;br /&gt;
                float * num = new float []();&lt;br /&gt;
                float den = 0;&lt;br /&gt;
                for (int j=0; j&amp;lt;n; j++){&lt;br /&gt;
                    num += pow(W[j][i], m) * X[j];&lt;br /&gt;
                    den+=pow(W[j][i], m);&lt;br /&gt;
                }&lt;br /&gt;
                centers[i] = num / den;&lt;br /&gt;
            }&lt;br /&gt;
            //обновляем вероятности W и считаем расстояние между матрицами W и Wprev&lt;br /&gt;
            float max_diff = 0;&lt;br /&gt;
            for (int i=0; i&amp;lt;n; i++)&lt;br /&gt;
                for (int j=0; j&amp;lt;c; j++){&lt;br /&gt;
                    total = 0;&lt;br /&gt;
                    for (int m=0; m&amp;lt;с; m++)&lt;br /&gt;
                        total += pow(distance(X[i], centers[j]) / distance(X[i], centers[m]), 2/(m-1));&lt;br /&gt;
                    W[i][j] = 1/total;&lt;br /&gt;
                    max_diff = max(abs(Wprev[i][j]-W[i][j]), max_diff);&lt;br /&gt;
                    Wprev[i][j] = W[i][j];&lt;br /&gt;
               }               &lt;br /&gt;
           if (max_diff &amp;lt; eps):                &lt;br /&gt;
                break;&lt;br /&gt;
        }&lt;br /&gt;
        return W;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Последовательная сложность алгоритма состоит из сложности каждой итерации умноженной на их количество. Так как число итераций заранее неизвестно и зависит от входных параметров, рассмотрим сложность на каждой итерации. Наибольшую сложность представляет собой пересчет матрицы, сложность которого &amp;lt;math&amp;gt;O(c^2 nd)&amp;lt;/math&amp;gt; (по сравнению со сложностью &amp;lt;math&amp;gt;O(cnd)&amp;lt;/math&amp;gt; расчета расстояний, вычисления центроидов и проверки условия останова). Итого общая сложность алгоритма &amp;lt;math&amp;gt;O(c^2 ndi)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* Входные данные алгоритма: набор векторов &amp;lt;math&amp;gt;x_i&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i = 1,...,M&amp;lt;/math&amp;gt;; M - количество векторов.&lt;br /&gt;
* Выходные данные алгоритма: матрица размерности &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
==Существующие реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=7731</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=7731"/>
		<updated>2016-10-14T15:59:03Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(ndc^2i)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - количество итераций&lt;br /&gt;
| input_data         = &amp;lt;math&amp;gt;n*d&amp;lt;/math&amp;gt;, [количество наблюдений * размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;n*c&amp;lt;/math&amp;gt;, [количество наблюдений * количество кластеров]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]], [[Участник:Yushin|Павел Юшин]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;{{Cite journal|last=Dunn|first=J. C.|date=1973-01-01|title=A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters|url=http://dx.doi.org/10.1080/01969727308546046|journal=Journal of Cybernetics|volume=3|issue=3|pages=32–57|doi=10.1080/01969727308546046|issn=0022-0280}}&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - экспоненциальный вес; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма будут отличать менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;0 &amp;lt; \sum_{i = 1}^M w_{ij} &amp;lt; M, j = 1, ..., c&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда алгоритм принимает следующий вид:&lt;br /&gt;
&lt;br /&gt;
1) Задаем параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
2) Генерируем случайным образом матрицу нечеткого разбиения с учетом условий &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3) Рассчитываем центроиды (центры кластеров): &amp;lt;math&amp;gt;V_j = {{\sum_{i=1}^M w_{ij}^m * X_i} \over {\sum_{i=1}^M w_{ij}^m}}, j = 1, ..., c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Рассчитываем расстояния между объектами &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и центроидами:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_{ij} = {||X_i - V_j||}, i = 1,...,M; j = 1,...,c &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5) Пересчет элементов матрицы разбиения:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} &amp;gt;0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = {{1}\over {{ (\sum_{k=1}^c {{D_{ij}}\over{D_{ik}}} ) }^{2/(m-1)}}}, j = 1,...,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} =0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = \delta_{ij}, j = 1,...,c&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\delta_{ij}&amp;lt;/math&amp;gt; - символ Кронекера&lt;br /&gt;
&lt;br /&gt;
6) Если &amp;lt;math&amp;gt;|| F - F^{*} || &amp;lt; \varepsilon &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;F^{*}&amp;lt;/math&amp;gt; - матрица нечеткого разбиения предыдущей итерации, то идем далее, иначе возвращаемся на пункт 3.&lt;br /&gt;
&lt;br /&gt;
7) Конец.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром алгоритма являются пункты (3), (4), (5) - расчет центроидов, вычисление расстояний и пересчет элементов матрицы соответственно&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Основные шаги при реализации алгоритма&lt;br /&gt;
*	Генерация случайной матрицы размера &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на где &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;, проверка условий&lt;br /&gt;
*	Расчет центроидов – по сути, скалярное произведение с нормировкой&lt;br /&gt;
*	Расчет расстояний – в общепринятом случае является скалярным произведением&lt;br /&gt;
*	Пересчет матрицы – по сути, скалярное произведение&lt;br /&gt;
*	Проверка условий останова – вычисление нормы&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
    float ** FuzzyCMeans (float** X, c, m, eps){&lt;br /&gt;
        n = X.size();&lt;br /&gt;
        r = X[0].size();&lt;br /&gt;
        centers = generateZeroFill(c, r)&lt;br /&gt;
        Wprev = genetateRandFill(n, c);&lt;br /&gt;
        W = Wprev;&lt;br /&gt;
        while (true){&lt;br /&gt;
            // обновляем центры кластеров &lt;br /&gt;
            for (int i=0; i&amp;lt;c; i++){&lt;br /&gt;
                float * num = new float []();&lt;br /&gt;
                float den = 0;&lt;br /&gt;
                for (int j=0; j&amp;lt;n; j++){&lt;br /&gt;
                    num += pow(W[j][i], m) * X[j];&lt;br /&gt;
                    den+=pow(W[j][i], m);&lt;br /&gt;
                }&lt;br /&gt;
                centers[i] = num / den;&lt;br /&gt;
            }&lt;br /&gt;
            //обновляем вероятности W и считаем расстояние между матрицами W и Wprev&lt;br /&gt;
            float max_diff = 0;&lt;br /&gt;
            for (int i=0; i&amp;lt;n; i++)&lt;br /&gt;
                for (int j=0; j&amp;lt;c; j++){&lt;br /&gt;
                    total = 0;&lt;br /&gt;
                    for (int m=0; m&amp;lt;с; m++)&lt;br /&gt;
                        total += pow(distance(X[i], centers[j]) / distance(X[i], centers[m]), 2/(m-1));&lt;br /&gt;
                    W[i][j] = 1/total;&lt;br /&gt;
                    max_diff = max(abs(Wprev[i][j]-W[i][j]), max_diff);&lt;br /&gt;
                    Wprev[i][j] = W[i][j];&lt;br /&gt;
               }               &lt;br /&gt;
           if (max_diff &amp;lt; eps):                &lt;br /&gt;
                break;&lt;br /&gt;
        }&lt;br /&gt;
        return W;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Последовательная сложность алгоритма состоит из сложности каждой итерации умноженной на их количество. Так как число итераций заранее неизвестно и зависит от входных параметров, рассмотрим сложность на каждой итерации. Наибольшую сложность представляет собой пересчет матрицы, сложность которого &amp;lt;math&amp;gt;O(c^2 nd)&amp;lt;/math&amp;gt; (по сравнению со сложностью &amp;lt;math&amp;gt;O(cnd)&amp;lt;/math&amp;gt; расчета расстояний, вычисления центроидов и проверки условия останова). Итого общая сложность алгоритма &amp;lt;math&amp;gt;O(c^2 ndi)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
==Существующие реализации алгоритма==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=7719</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=7719"/>
		<updated>2016-10-14T15:54:50Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(ndc^2i)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - количество итераций&lt;br /&gt;
| input_data         = &amp;lt;math&amp;gt;n*d&amp;lt;/math&amp;gt;, [количество наблюдений * размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;n*c&amp;lt;/math&amp;gt;, [количество наблюдений * количество кластеров]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]], [[Участник:Yushin|Павел Юшин]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;{{Cite journal|last=Dunn|first=J. C.|date=1973-01-01|title=A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters|url=http://dx.doi.org/10.1080/01969727308546046|journal=Journal of Cybernetics|volume=3|issue=3|pages=32–57|doi=10.1080/01969727308546046|issn=0022-0280}}&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - экспоненциальный вес; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма будут отличать менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;0 &amp;lt; \sum_{i = 1}^M w_{ij} &amp;lt; M, j = 1, ..., c&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда алгоритм принимает следующий вид:&lt;br /&gt;
&lt;br /&gt;
1) Задаем параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
2) Генерируем случайным образом матрицу нечеткого разбиения с учетом условий &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3) Рассчитываем центроиды (центры кластеров): &amp;lt;math&amp;gt;V_j = {{\sum_{i=1}^M w_{ij}^m * X_i} \over {\sum_{i=1}^M w_{ij}^m}}, j = 1, ..., c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Рассчитываем расстояния между объектами &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и центроидами:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_{ij} = {||X_i - V_j||}, i = 1,...,M; j = 1,...,c &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5) Пересчет элементов матрицы разбиения:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} &amp;gt;0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = {{1}\over {{ (\sum_{k=1}^c {{D_{ij}}\over{D_{ik}}} ) }^{2/(m-1)}}}, j = 1,...,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ij} =0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{ij} = \delta_{ij}, j = 1,...,c&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\delta_{ij}&amp;lt;/math&amp;gt; - символ Кронекера&lt;br /&gt;
&lt;br /&gt;
6) Если &amp;lt;math&amp;gt;|| F - F^{*} || &amp;lt; \varepsilon &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;F^{*}&amp;lt;/math&amp;gt; - матрица нечеткого разбиения предыдущей итерации, то идем далее, иначе возвращаемся на пункт 3.&lt;br /&gt;
&lt;br /&gt;
7) Конец.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром алгоритма являются пункты (3), (4), (5) - расчет центроидов, вычисление расстояний и пересчет элементов матрицы соответственно&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Основные шаги при реализации алгоритма&lt;br /&gt;
*	Генерация случайной матрицы размера &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на где &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;, проверка условий&lt;br /&gt;
*	Расчет центроидов – по сути, скалярное произведение с нормировкой&lt;br /&gt;
*	Расчет расстояний – в общепринятом случае является скалярным произведением&lt;br /&gt;
*	Пересчет матрицы – по сути, скалярное произведение&lt;br /&gt;
*	Проверка условий останова – вычисление нормы&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
    float ** FuzzyCMeans (float** X, c, m, eps){&lt;br /&gt;
        n = X.size();&lt;br /&gt;
        r = X[0].size();&lt;br /&gt;
        centers = generateZeroFill(c, r)&lt;br /&gt;
        Wprev = genetateRandFill(n, c);&lt;br /&gt;
        W = Wprev;&lt;br /&gt;
        while (true){&lt;br /&gt;
            // обновляем центры кластеров &lt;br /&gt;
            for (int i=0; i&amp;lt;c; i++){&lt;br /&gt;
                float * num = new float []();&lt;br /&gt;
                float den = 0;&lt;br /&gt;
                for (int j=0; j&amp;lt;n; j++){&lt;br /&gt;
                    num += pow(W[j][i], m) * X[j];&lt;br /&gt;
                    den+=pow(W[j][i], m);&lt;br /&gt;
                }&lt;br /&gt;
                centers[i] = num / den;&lt;br /&gt;
            }&lt;br /&gt;
            //обновляем вероятности W и считаем расстояние между матрицами W и Wprev&lt;br /&gt;
            float max_diff = 0;&lt;br /&gt;
            for (int i=0; i&amp;lt;n; i++)&lt;br /&gt;
                for (int j=0; j&amp;lt;c; j++){&lt;br /&gt;
                    total = 0;&lt;br /&gt;
                    for (int m=0; m&amp;lt;с; m++)&lt;br /&gt;
                        total += pow(distance(X[i], centers[j]) / distance(X[i], centers[m]), 2/(m-1));&lt;br /&gt;
                    W[i][j] = 1/total;&lt;br /&gt;
                    max_diff = max(abs(Wprev[i][j]-W[i][j]), max_diff);&lt;br /&gt;
                    Wprev[i][j] = W[i][j];&lt;br /&gt;
               }               &lt;br /&gt;
           if (max_diff &amp;lt; eps):                &lt;br /&gt;
                break;&lt;br /&gt;
        }&lt;br /&gt;
        return W;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Последовательная сложность алгоритма состоит из сложности каждой итерации умноженной на их количество. Так как число итераций заранее неизвестно и зависит от входных параметров, рассмотрим сложность на каждой итерации. Наибольшую сложность представляет собой пересчет матрицы, сложность которого &amp;lt;math&amp;gt;O(c^2 nd)&amp;lt;/math&amp;gt; (по сравнению со сложностью &amp;lt;math&amp;gt;O(cnd)&amp;lt;/math&amp;gt; расчета расстояний, вычисления центроидов и проверки условия останова). Итого общая сложность алгоритма &amp;lt;math&amp;gt;O(c^2 ndi)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=5408</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=5408"/>
		<updated>2016-10-11T17:42:14Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(ndc^2i)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - количество итераций&lt;br /&gt;
| input_data         = &amp;lt;math&amp;gt;n*d&amp;lt;/math&amp;gt;, [количество наблюдений * размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;n*c&amp;lt;/math&amp;gt;, [количество наблюдений * количество кластеров]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]], [[Участник:Yushin|Павел Юшин]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;{{Cite journal|last=Dunn|first=J. C.|date=1973-01-01|title=A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters|url=http://dx.doi.org/10.1080/01969727308546046|journal=Journal of Cybernetics|volume=3|issue=3|pages=32–57|doi=10.1080/01969727308546046|issn=0022-0280}}&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - экспоненциальный вес; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма будут отличать менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;0 &amp;lt; \sum_{i = 1}^M w_{ij} &amp;lt; M, j = 1, ..., c&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда алгоритм принимает следующий вид:&lt;br /&gt;
&lt;br /&gt;
1) Задаем параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
2) Генерируем случайным образом матрицу нечеткого разбиения с учетом условий &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3) Рассчитываем центроиды (центры кластеров): &amp;lt;math&amp;gt;V_j = {{\sum_{i=1}^M w_{ij}^m * |X_i|} \over {\sum_{i=1}^M w_{ij}^m}}, j = 1, ..., c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Рассчитываем расстояния между объектами &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и центроидами:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_{ij} = \sqrt{{||X_i - V_j||}^2}, i = 1,...,M; j = 1,...,c &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5) Пересчет элементов матрицы разбиения:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ki} &amp;gt;0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{kj} = {{1}\over {{ ( D_{jk}^2 * \sum_{j=1}^c {{1}\over{D_{jk}^2}} ) }^{1/(m-1)}}}, j = 1,...,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ki} =0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{kj} = \delta_{ji}, j = 1,...,c&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\delta_{ji}&amp;lt;/math&amp;gt; - символ Кронекера&lt;br /&gt;
&lt;br /&gt;
6) Если &amp;lt;math&amp;gt;|| F - F^{*} || &amp;lt; \varepsilon &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;F^{*}&amp;lt;/math&amp;gt; - матрица нечеткого разбиения предыдущей итерации, то идем далее, иначе возвращаемся на пункт 3.&lt;br /&gt;
&lt;br /&gt;
7) Конец.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром алгоритма являются пункты (3), (4), (5) - расчет центроидов, вычисление расстояний и пересчет элементов матрицы соответственно&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Основные шаги при реализации алгоритма&lt;br /&gt;
*	Генерация случайной матрицы размера &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; на где &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;, проверка условий&lt;br /&gt;
*	Расчет центроидов – по сути, скалярное произведение с нормировкой&lt;br /&gt;
*	Расчет расстояний – в общепринятом случае является скалярным произведением&lt;br /&gt;
*	Пересчет матрицы – по сути, скалярное произведение&lt;br /&gt;
*	Проверка условий останова – вычисление нормы&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Последовательная сложность алгоритма состоит из сложности каждой итерации умноженной на их количество. Так как число итераций заранее неизвестно и зависит от входных параметров, рассмотрим сложность на каждой итерации. Наибольшую сложность представляет собой расчет центроидов, сложность которого &amp;lt;math&amp;gt;O(c^2 nd)&amp;lt;/math&amp;gt; (по сравнению со сложностью &amp;lt;math&amp;gt;O(cnd)&amp;lt;/math&amp;gt; расчета расстояний, пересчета матрицы и проверки условия останова). Итого общая сложность алгоритма &amp;lt;math&amp;gt;O(c^2 ndi)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=5278</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=5278"/>
		<updated>2016-10-10T22:43:33Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(ndc^2i)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - количество итераций&lt;br /&gt;
| input_data         = &amp;lt;math&amp;gt;n*d&amp;lt;/math&amp;gt;, [количество наблюдений x размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;n*c&amp;lt;/math&amp;gt;, [количество наблюдений x количество кластеров]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]], [[Участник:Yushin|Павел Юшин]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;{{Cite journal|last=Dunn|first=J. C.|date=1973-01-01|title=A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters|url=http://dx.doi.org/10.1080/01969727308546046|journal=Journal of Cybernetics|volume=3|issue=3|pages=32–57|doi=10.1080/01969727308546046|issn=0022-0280}}&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - экспоненциальный вес; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма будут отличать менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;0 &amp;lt; \sum_{i = 1}^M w_{ij} &amp;lt; M, j = 1, ..., c&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда алгоритм принимает следующий вид:&lt;br /&gt;
&lt;br /&gt;
1) Задаем параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
2) Генерируем случайным образом матрицу нечеткого разбиения с учетом условий &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3) Рассчитываем центроиды (центры кластеров): &amp;lt;math&amp;gt;V_i = {{\sum_{i=1}^M w_{ij}^m * |X_i|} \over {\sum_{i=1}^M w_{ij}^m}}, j = 1, ..., c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Рассчитываем расстояния между объектами &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и центроидами:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_{ij} = \sqrt{{||X_i - V_j||}^2}, i = 1,...,M; j = 1,...,c &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5) Пересчет элементов матрицы разбиения:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ki} &amp;gt;0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{kj} = {{1}\over {{ ( D_{jk}^2 * \sum_{j=1}^c {{1}\over{D_{jk}^2}} ) }^{1/(m-1)}}}, j = 1,...,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ki} =0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{kj} = \delta_{ji}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\delta_{ji}&amp;lt;/math&amp;gt; - символ Кронекера&lt;br /&gt;
&lt;br /&gt;
6) Если &amp;lt;math&amp;gt;|| F - F^{*} || &amp;lt; \varepsilon &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;F^{*}&amp;lt;/math&amp;gt; - матрица нечеткого разбиения предыдущей итерации, то идем далее, иначе возвращаемся на пункт 3.&lt;br /&gt;
&lt;br /&gt;
7) Конец.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=5277</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=5277"/>
		<updated>2016-10-10T22:43:14Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(ndc^2i)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;i&amp;lt;\math&amp;gt; - количество итераций&lt;br /&gt;
| input_data         = &amp;lt;math&amp;gt;n*d&amp;lt;/math&amp;gt;, [количество наблюдений x размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;n*c&amp;lt;/math&amp;gt;, [количество наблюдений x количество кластеров]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]], [[Участник:Yushin|Павел Юшин]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;{{Cite journal|last=Dunn|first=J. C.|date=1973-01-01|title=A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters|url=http://dx.doi.org/10.1080/01969727308546046|journal=Journal of Cybernetics|volume=3|issue=3|pages=32–57|doi=10.1080/01969727308546046|issn=0022-0280}}&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - экспоненциальный вес; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма будут отличать менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;0 &amp;lt; \sum_{i = 1}^M w_{ij} &amp;lt; M, j = 1, ..., c&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда алгоритм принимает следующий вид:&lt;br /&gt;
&lt;br /&gt;
1) Задаем параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
2) Генерируем случайным образом матрицу нечеткого разбиения с учетом условий &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3) Рассчитываем центроиды (центры кластеров): &amp;lt;math&amp;gt;V_i = {{\sum_{i=1}^M w_{ij}^m * |X_i|} \over {\sum_{i=1}^M w_{ij}^m}}, j = 1, ..., c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Рассчитываем расстояния между объектами &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и центроидами:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_{ij} = \sqrt{{||X_i - V_j||}^2}, i = 1,...,M; j = 1,...,c &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5) Пересчет элементов матрицы разбиения:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ki} &amp;gt;0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{kj} = {{1}\over {{ ( D_{jk}^2 * \sum_{j=1}^c {{1}\over{D_{jk}^2}} ) }^{1/(m-1)}}}, j = 1,...,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ki} =0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{kj} = \delta_{ji}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\delta_{ji}&amp;lt;/math&amp;gt; - символ Кронекера&lt;br /&gt;
&lt;br /&gt;
6) Если &amp;lt;math&amp;gt;|| F - F^{*} || &amp;lt; \varepsilon &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;F^{*}&amp;lt;/math&amp;gt; - матрица нечеткого разбиения предыдущей итерации, то идем далее, иначе возвращаемся на пункт 3.&lt;br /&gt;
&lt;br /&gt;
7) Конец.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=5275</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=5275"/>
		<updated>2016-10-10T22:12:53Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(ncl)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data         = &amp;lt;math&amp;gt;n*d&amp;lt;/math&amp;gt;, [количество наблюдений x размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;n*c&amp;lt;/math&amp;gt;, [количество наблюдений x количество кластеров]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]], [[Участник:Yushin|Павел Юшин]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;{{Cite journal|last=Dunn|first=J. C.|date=1973-01-01|title=A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters|url=http://dx.doi.org/10.1080/01969727308546046|journal=Journal of Cybernetics|volume=3|issue=3|pages=32–57|doi=10.1080/01969727308546046|issn=0022-0280}}&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - экспоненциальный вес; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма будут отличать менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;0 &amp;lt; \sum_{i = 1}^M w_{ij} &amp;lt; M, j = 1, ..., c&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда алгоритм принимает следующий вид:&lt;br /&gt;
&lt;br /&gt;
1) Задаем параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
2) Генерируем случайным образом матрицу нечеткого разбиения с учетом условий &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3) Рассчитываем центроиды (центры кластеров): &amp;lt;math&amp;gt;V_i = {{\sum_{i=1}^M w_{ij}^m * |X_i|} \over {\sum_{i=1}^M w_{ij}^m}}, j = 1, ..., c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Рассчитываем расстояния между объектами &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и центроидами:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_{ij} = \sqrt{{||X_i - V_j||}^2}, i = 1,...,M; j = 1,...,c &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5) Пересчет элементов матрицы разбиения:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ki} &amp;gt;0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{kj} = {{1}\over {{ ( D_{jk}^2 * \sum_{j=1}^c {{1}\over{D_{jk}^2}} ) }^{1/(m-1)}}}, j = 1,...,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ki} =0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{kj} = \delta_{ji}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\delta_{ji}&amp;lt;/math&amp;gt; - символ Кронекера&lt;br /&gt;
&lt;br /&gt;
6) Если &amp;lt;math&amp;gt;|| F - F^{*} || &amp;lt; \varepsilon &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;F^{*}&amp;lt;/math&amp;gt; - матрица нечеткого разбиения предыдущей итерации, то идем далее, иначе возвращаемся на пункт 3.&lt;br /&gt;
&lt;br /&gt;
7) Конец.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=5274</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=5274"/>
		<updated>2016-10-10T22:12:21Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(ncl)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data         = &amp;lt;math&amp;gt;n*d&amp;lt;/math&amp;gt;, [количество наблюдений x размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;n*c&amp;lt;/math&amp;gt;, [количество наблюдений x количество кластеров]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]], [[Участник:Yushin|Павел Юшин]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;{{Cite journal|last=Dunn|first=J. C.|date=1973-01-01|title=A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters|url=http://dx.doi.org/10.1080/01969727308546046|journal=Journal of Cybernetics|volume=3|issue=3|pages=32–57|doi=10.1080/01969727308546046|issn=0022-0280}}&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - экспоненциальный вес; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма будут отличать менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;0 &amp;lt; \sum_{i = 1}^M w_{ij} &amp;lt; M, j = 1, ..., c&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда алгоритм принимает следующий вид:&lt;br /&gt;
&lt;br /&gt;
1) Задаем параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
2) Генерируем случайным образом матрицу нечеткого разбиения с учетом условий &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3) Рассчитываем центроиды (центры кластеров): &amp;lt;math&amp;gt;V_i = {{\sum_{i=1}^M w_{ij}^m * |X_i|} \over {\sum_{i=1}^M w{ij}^m}}, j = 1, ..., c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Рассчитываем расстояния между объектами &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и центроидами:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_{ij} = \sqrt{{||X_i - V_j||}^2}, i = 1,...,M; j = 1,...,c &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5) Пересчет элементов матрицы разбиения:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ki} &amp;gt;0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{kj} = {{1}\over {{ ( D_{jk}^2 * \sum_{j=1}^c {{1}\over{D_{jk}^2}} ) }^{1/(m-1)}}}, j = 1,...,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ki} =0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{kj} = \delta_{ji}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\delta_{ji}&amp;lt;/math&amp;gt; - символ Кронекера&lt;br /&gt;
&lt;br /&gt;
6) Если &amp;lt;math&amp;gt;|| F - F^{*} || &amp;lt; \varepsilon &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;F^{*}&amp;lt;/math&amp;gt; - матрица нечеткого разбиения предыдущей итерации, то идем далее, иначе возвращаемся на пункт 3.&lt;br /&gt;
&lt;br /&gt;
7) Конец.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=5273</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=5273"/>
		<updated>2016-10-10T22:11:32Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(ncl)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;n*d&amp;lt;/math&amp;gt;, [количество наблюдений x размерность]&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;n*c&amp;lt;/math&amp;gt;, [количество наблюдений x количество кластеров]&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]], [[Участник:Yushin|Павел Юшин]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;{{Cite journal|last=Dunn|first=J. C.|date=1973-01-01|title=A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters|url=http://dx.doi.org/10.1080/01969727308546046|journal=Journal of Cybernetics|volume=3|issue=3|pages=32–57|doi=10.1080/01969727308546046|issn=0022-0280}}&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - экспоненциальный вес; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма будут отличать менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;0 &amp;lt; \sum_{i = 1}^M w_{ij} &amp;lt; M, j = 1, ..., c&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда алгоритм принимает следующий вид:&lt;br /&gt;
&lt;br /&gt;
1) Задаем параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
2) Генерируем случайным образом матрицу нечеткого разбиения с учетом условий &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3) Рассчитываем центроиды (центры кластеров): &amp;lt;math&amp;gt;V_i = {{\sum_{i=1}^M w_{ij}^m * |X_i|} \over {\sum_{i=1}^M w{ij}^m}}, j = 1, ..., c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Рассчитываем расстояния между объектами &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и центроидами:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_{ij} = \sqrt{{||X_i - V_j||}^2}, i = 1,...,M; j = 1,...,c &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5) Пересчет элементов матрицы разбиения:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ki} &amp;gt;0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{kj} = {{1}\over {{ ( D_{jk}^2 * \sum_{j=1}^c {{1}\over{D_{jk}^2}} ) }^{1/(m-1)}}}, j = 1,...,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ki} =0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{kj} = \delta_{ji}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\delta_{ji}&amp;lt;/math&amp;gt; - символ Кронекера&lt;br /&gt;
&lt;br /&gt;
6) Если &amp;lt;math&amp;gt;|| F - F^{*} || &amp;lt; \varepsilon &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;F^{*}&amp;lt;/math&amp;gt; - матрица нечеткого разбиения предыдущей итерации, то идем далее, иначе возвращаемся на пункт 3.&lt;br /&gt;
&lt;br /&gt;
7) Конец.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=5271</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=5271"/>
		<updated>2016-10-10T21:58:00Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(ncl)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]], [[Участник:Yushin|Павел Юшин]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;{{Cite journal|last=Dunn|first=J. C.|date=1973-01-01|title=A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters|url=http://dx.doi.org/10.1080/01969727308546046|journal=Journal of Cybernetics|volume=3|issue=3|pages=32–57|doi=10.1080/01969727308546046|issn=0022-0280}}&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - экспоненциальный вес; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма будут отличать менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;0 &amp;lt; \sum_{i = 1}^M w_{ij} &amp;lt; M, j = 1, ..., c&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда алгоритм принимает следующий вид:&lt;br /&gt;
&lt;br /&gt;
1) Задаем параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
2) Генерируем случайным образом матрицу нечеткого разбиения с учетом условий &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3) Рассчитываем центроиды (центры кластеров): &amp;lt;math&amp;gt;V_i = {{\sum_{i=1}^M w_{ij}^m * |X_i|} \over {\sum_{i=1}^M w{ij}^m}}, j = 1, ..., c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Рассчитываем расстояния между объектами &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и центроидами:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_{ij} = \sqrt{{||X_i - V_j||}^2}, i = 1,...,M; j = 1,...,c &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5) Пересчет элементов матрицы разбиения:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ki} &amp;gt;0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{kj} = {{1}\over {{ ( D_{jk}^2 * \sum_{j=1}^c {{1}\over{D_{jk}^2}} ) }^{1/(m-1)}}}, j = 1,...,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ki} =0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{kj} = \delta_{ji}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\delta_{ji}&amp;lt;/math&amp;gt; - символ Кронекера&lt;br /&gt;
&lt;br /&gt;
6) Если &amp;lt;math&amp;gt;|| F - F^{*} || &amp;lt; \varepsilon &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;F^{*}&amp;lt;/math&amp;gt; - матрица нечеткого разбиения предыдущей итерации, то идем далее, иначе возвращаемся на пункт 3.&lt;br /&gt;
&lt;br /&gt;
7) Конец.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=5268</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=5268"/>
		<updated>2016-10-10T21:44:16Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]], [[Участник:Yushin|Павел Юшин]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;{{Cite journal|last=Dunn|first=J. C.|date=1973-01-01|title=A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters|url=http://dx.doi.org/10.1080/01969727308546046|journal=Journal of Cybernetics|volume=3|issue=3|pages=32–57|doi=10.1080/01969727308546046|issn=0022-0280}}&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - экспоненциальный вес; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма будут отличать менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;0 &amp;lt; \sum_{i = 1}^M w_{ij} &amp;lt; M, j = 1, ..., c&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда алгоритм принимает следующий вид:&lt;br /&gt;
&lt;br /&gt;
1) Задаем параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
2) Генерируем случайным образом матрицу нечеткого разбиения с учетом условий &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3) Рассчитываем центроиды (центры кластеров): &amp;lt;math&amp;gt;V_i = {{\sum_{i=1}^M w_{ij}^m * |X_i|} \over {\sum_{i=1}^M w{ij}^m}}, j = 1, ..., c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Рассчитываем расстояния между объектами &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и центроидами:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_{ij} = \sqrt{{||X_i - V_j||}^2}, i = 1,...,M; j = 1,...,c &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5) Пересчет элементов матрицы разбиения:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ki} &amp;gt;0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{kj} = {{1}\over {{ ( D_{jk}^2 * \sum_{j=1}^c {{1}\over{D_{jk}^2}} ) }^{1/(m-1)}}}, j = 1,...,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ki} =0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{kj} = \delta_{ji}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\delta_{ji}&amp;lt;/math&amp;gt; - символ Кронекера&lt;br /&gt;
&lt;br /&gt;
6) Если &amp;lt;math&amp;gt;|| F - F^{*} || &amp;lt; \varepsilon &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;F^{*}&amp;lt;/math&amp;gt; - матрица нечеткого разбиения предыдущей итерации, то идем далее, иначе возвращаемся на пункт 3.&lt;br /&gt;
&lt;br /&gt;
7) Конец.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=5264</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=5264"/>
		<updated>2016-10-10T21:25:45Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]], [[Участник:Yushin|Павел Юшин]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;{{Cite journal|last=Dunn|first=J. C.|date=1973-01-01|title=A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters|url=http://dx.doi.org/10.1080/01969727308546046|journal=Journal of Cybernetics|volume=3|issue=3|pages=32–57|doi=10.1080/01969727308546046|issn=0022-0280}}&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - экспоненциальный вес; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма будут отличать менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;0 &amp;lt; \sum_{i = 1}^M w_{ij} &amp;lt; M, j = 1, ..., c&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда алгоритм принимает следующий вид:&lt;br /&gt;
&lt;br /&gt;
1) Задаем параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
2) Генерируем случайным образом матрицу нечеткого разбиения с учетом условий &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3) Рассчитываем центроиды (центры кластеров): &amp;lt;math&amp;gt;V_i = {{\sum_{i=1}^M w_{ij}^m * |X_i|} \over {\sum_{i=1}^M w{ij}^m}}, j = 1, ..., c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Рассчитываем расстояния между объектами &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и центроидами:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_{ij} = \sqrt{{||X_i - V_j||}^2}, i = 1,...,M; j = 1,...,c &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5) Пересчет элементов матрицы разбиения:&lt;br /&gt;
&lt;br /&gt;
при &amp;lt;math&amp;gt;D_{ki} &amp;gt;0&amp;lt;/math&amp;gt; : &amp;lt;math&amp;gt;w_{kj} = {{1}\over {{D_{jk}^2 * \sum_{j=1}^c {{1}\over{D_{jk}^2}}}^{1/(m-1)}}}, j = 1,...,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=5262</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=5262"/>
		<updated>2016-10-10T21:15:27Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]], [[Участник:Yushin|Павел Юшин]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;{{Cite journal|last=Dunn|first=J. C.|date=1973-01-01|title=A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters|url=http://dx.doi.org/10.1080/01969727308546046|journal=Journal of Cybernetics|volume=3|issue=3|pages=32–57|doi=10.1080/01969727308546046|issn=0022-0280}}&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - экспоненциальный вес; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма будут отличать менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;0 &amp;lt; \sum_{i = 1}^M w_{ij} &amp;lt; M, j = 1, ..., c&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Тогда алгоритм принимает следующий вид:&lt;br /&gt;
&lt;br /&gt;
1) Задаем параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m &amp;gt;= 1&amp;lt;/math&amp;gt; - экспоненциальный вес, определяющий нечеткость кластеров; &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
2) Генерируем случайным образом матрицу нечеткого разбиения с учетом условий &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3) Рассчитываем центроиды (центры кластеров): &amp;lt;math&amp;gt;V_i = {{\sum_{i=1}^M w_{ij}^m * |X_i|} \over {\sum_{i=1}^M w{ij}^m}}, j = 1, ..., c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=5261</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=5261"/>
		<updated>2016-10-10T20:59:45Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]], [[Участник:Yushin|Павел Юшин]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;{{Cite journal|last=Dunn|first=J. C.|date=1973-01-01|title=A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters|url=http://dx.doi.org/10.1080/01969727308546046|journal=Journal of Cybernetics|volume=3|issue=3|pages=32–57|doi=10.1080/01969727308546046|issn=0022-0280}}&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - экспоненциальный вес; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма будут отличать менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;0 &amp;lt; \sum_{i = 1}^M w_{ij} &amp;lt; M, j = 1, ..., c&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=5260</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=5260"/>
		<updated>2016-10-10T20:57:49Z</updated>

		<summary type="html">&lt;p&gt;Yushin: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Gkhazeeva|Гелана Хазеева]], [[Участник:Yushin|Павел Юшин]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация - это объединение объектов в группы (кластеры) на основе схожести признаков для объектов одной группы и отличий между группами. Нечеткий алгоритм C Средних (Fuzzy C-means, FCM) - алгоритм кластеризации, позволяющий объектам принадлежать с различной степенью нескольким кластерам одновременно. Впервые алгоритм был предложен J.C. Dunn в 1973 &amp;lt;ref&amp;gt;{{Cite journal|last=Dunn|first=J. C.|date=1973-01-01|title=A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters|url=http://dx.doi.org/10.1080/01969727308546046|journal=Journal of Cybernetics|volume=3|issue=3|pages=32–57|doi=10.1080/01969727308546046|issn=0022-0280}}&amp;lt;/ref&amp;gt;. Нечеткое разбиение позволяет просто решить проблему объектов, расположенных на границе двух кластеров - им назначают степени принадлежностей равные 0.5.&lt;br /&gt;
&lt;br /&gt;
Входные данные алгоритма: набор векторов, которые следует кластеризовать.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров; &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - экспоненциальный вес; &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - параметр останова алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные: матрица вероятностей принадлежности векторов кластерам.&lt;br /&gt;
&lt;br /&gt;
Краткое описание алгоритма:&lt;br /&gt;
&lt;br /&gt;
* Задать параметры алгоритма.&lt;br /&gt;
&lt;br /&gt;
* Сгенерировать случайную матрицу принадлежностей векторов кластерам (матрицу нечеткого разбиения).&lt;br /&gt;
&lt;br /&gt;
* Повторить следующие шаги до момента, пока матрицы нечеткого разбиения на этом и предыдущем шаге алгоритма будут отличать менее чем на параметр останова.&lt;br /&gt;
** Рассчитать центры кластеров.&lt;br /&gt;
** Рассчитать расстоение между объектами и центрами кластеров.&lt;br /&gt;
** Пересчитать элементы матрицы нечеткого разбиения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма &amp;lt;ref&amp;gt;http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf&amp;lt;/ref&amp;gt; ==&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt; W = w_{ij} \in[0,1],\; i = 1, ..., M, \; j = 1, ..., c&amp;lt;/math&amp;gt; - матрица разбиения, где &amp;lt;math&amp;gt;w_{i,j}&amp;lt;/math&amp;gt; - степень принадлежности объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество векторов.&lt;br /&gt;
&lt;br /&gt;
При этом элементы матрицы должны удовлетворять условиям&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;/sum_{j = 1}^c w_{ij} = 1, i = 1, ..., M (1)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Yushin</name></author>
	</entry>
</feed>