<?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=ADovganich</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=ADovganich"/>
	<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/ADovganich"/>
	<updated>2026-10-22T23:56:15Z</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=21441</id>
		<title>Участник:ADovganich/Нечеткий алгоритм С средних</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=21441"/>
		<updated>2016-12-19T23:51:58Z</updated>

		<summary type="html">&lt;p&gt;ADovganich: /* Ресурс параллелизма алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|ASA}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(C*C*K*N*I)&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;K*N&amp;lt;/math&amp;gt;, [количество векторов * размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;C*K&amp;lt;/math&amp;gt;, [элементы матрицы принадлежности]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;3I&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;C*C*K&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Protsenko|Мария Проценко]] (1.5-1.8, 2.7), [[Участник:ADovganich|Андрей Довганич]] (1.1-1.4, 1.9, 1.10)&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Нечеткий алгоритм C-средних (fuzzy C-means) позволяет разбить имеющееся множество векторов (точек) мощностью &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; на заданное число нечетких множеств. Предназначен для кластеризации больших наборов данных. Основным достоинством алгоритма является нечеткость при определении объекта в кластер. Благодаря этому становится возможным определить объекты, которые находятся на границе, в кластеры. Из основного достоинства следует и главный недостаток - неопределенность с объектами, удаленными от центров всех кластеров. В остальном ему присущи стандартные проблемы подобного класса алгоритмов: вычислительная сложность, необходимость задания количества кластеров&amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм был разработан J.C. Dunn в 1973 г.&amp;lt;ref&amp;gt; Dunn, J. C. (1973-01-01). &amp;quot;A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters&amp;quot;. Journal of Cybernetics. 3 (3): 32–57. doi:10.1080/01969727308546046. ISSN 0022-0280.&amp;lt;/ref&amp;gt;, усовершенствован J.C. Bezdek в 1981 г.&amp;lt;ref&amp;gt; Bezdek, James C. (1981). Pattern Recognition with Fuzzy Objective Function Algorithms. ISBN 0-306-40671-3.&amp;lt;/ref&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;
# Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим матрицу &amp;lt;math&amp;gt; M = m_{ik} \in[0,1],\;  i = 1, ..., c, \; k = 1, ..., K &amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;m_{i,k}&amp;lt;/math&amp;gt; - вероятность принадлежности объекта &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; - количество векторов. При этом элементы матрицы удовлетворяют следующим условиям:&lt;br /&gt;
&lt;br /&gt;
* сумма элементов в каждом столбце равна &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* сумма всех элементов матрицы равно &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Назовем &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; матрицей принадлежности.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; - центры кластеров. Тогда рассмотрим функцию &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
J(M, c_{1}, c_{2},...c_{c}) = \sum_{i = 1}^{c}{J_{i}} = \sum_{i = 1}^{c}\sum_{k = 1}^{K}{m_{ik}^q}d_{ik}^2 ~(1)&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt; d_{ik} = \left\Vert{u_{k}-c_{i}}\right\| &amp;lt;/math&amp;gt; - Евклидово расстояние между центром кластера и объектом, &amp;lt;math&amp;gt; 1 \le q \le \infty &amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость. Будем минимизировать значение функции &amp;lt;math&amp;gt; J &amp;lt;/math&amp;gt;. Для этого вычислим центры кластеров по формуле &amp;lt;math&amp;gt; ~(2) &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c_{i} = {{\sum_{k = 1}^{K}{m_{ik}^q} * u_{k}} \over {\sum_{k = 1}^{K}{m_{ik}^q}}}~(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;m_{ik}&amp;lt;/math&amp;gt; — коэффициент принадлежности &amp;lt;math&amp;gt;u_{k}&amp;lt;/math&amp;gt; вектора к кластеру &amp;lt;math&amp;gt;c_{i}&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
и новые значения матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; по формуле &amp;lt;math&amp;gt; ~(3) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;m_{ik} = {1 \over \sum_{j = 1}^{c}{({{d_{ik}} \over {d_{jk}}})}^{2 \over q-1}} ~(3)&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; ~(2) &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; ~(3) &amp;lt;/math&amp;gt;являются необходимым условиями достижения минимума функцией &amp;lt;math&amp;gt; J &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; случайными значениями от 0 до 1;&lt;br /&gt;
# Вычислить центры кластеров &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; используя формулу &amp;lt;math&amp;gt;~(2)&amp;lt;/math&amp;gt;;&lt;br /&gt;
# Вычислить значение решающей функции по формуле &amp;lt;math&amp;gt;~(1)&amp;lt;/math&amp;gt;. Если значение &amp;lt;math&amp;gt; J &amp;lt; \varepsilon,~\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt; |J_{i} - J_{i-1}| &amp;lt; \delta,~\delta &amp;gt; 0 &amp;lt;/math&amp;gt;, то остановить вычисления;&lt;br /&gt;
# Иначе вычислить новые значения матрицы М по формуле &amp;lt;math&amp;gt;~(3)&amp;lt;/math&amp;gt;;&lt;br /&gt;
# Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительным ядром алгоритма являются формулы: &amp;lt;math&amp;gt; (1) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (2) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (3) &amp;lt;/math&amp;gt;. В них производится вычисление новых центров кластеров, значения решающей функции и пересчет элементов матрицы принадлежности.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Макроструктура алгоритма состоит из следующих шагов:&lt;br /&gt;
&lt;br /&gt;
# Инициализация матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; случайными значениями от 0 до 1;&lt;br /&gt;
# Вычисление центров кластеров; &lt;br /&gt;
# Вычисление значения решающей функции(если оно удовлетворяет условиям останова - завершение вычислений);&lt;br /&gt;
# Вычисление новых элементов матрицы принадлежности;&lt;br /&gt;
# Переход к шагу 2;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации алгоритма на языке С++. Сначала вычислим центры кластеров, потом вычислим решающую функцию, с ее помощью определим необходимость продолжать алгоритм, и при необходимости вычислим новые значения матрицы M.&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    float ** m;&lt;br /&gt;
    int *c;&lt;br /&gt;
    int number_clusters, number_items;&lt;br /&gt;
    m = gen_random_clusters();//заполним матрицу m случайными значениями от 0 до 1&lt;br /&gt;
    &lt;br /&gt;
    while (true)&lt;br /&gt;
    {&lt;br /&gt;
      //вычисление центров кластеров&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
        {&lt;br /&gt;
            numerator==denumerator=0;&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
            {&lt;br /&gt;
                numerator+=pow(m[i, k], q)*u[k];//u[k]-вектор&lt;br /&gt;
                denumerator+=pow(m[i, k], q);&lt;br /&gt;
            }&lt;br /&gt;
        c[i]= numerator / denumerator;//центры кластеров&lt;br /&gt;
        }&lt;br /&gt;
    &lt;br /&gt;
        j=0;//вычисление решающей функции&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
                j+=pow(m[i, k], q)*pow(dist(c[i], x[k],2);//dist-вычисляет расстояние между заданными векторами&lt;br /&gt;
    &lt;br /&gt;
       if ((abs(j-last_j)&amp;lt;delta) || (j&amp;lt;eps)) break;//проверка на необходимость завернешения алгоритма&lt;br /&gt;
       last_j=j;&lt;br /&gt;
     //обновление матрицы m&lt;br /&gt;
       for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
          for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
             {&lt;br /&gt;
               m[i,k]=0&lt;br /&gt;
              for(int j=0; j&amp;lt;number_clusters; j++)&lt;br /&gt;
                  m[i,k]+=pow(dist(c[i], x[k])/dist(c[j], x[k]),2/(q-1));&lt;br /&gt;
              m[i,k]=1/m[i,k];&lt;br /&gt;
              }&lt;br /&gt;
                                       &lt;br /&gt;
    }&lt;br /&gt;
    &amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Каждая итерация включает в себя&lt;br /&gt;
* Вычисление центров кластеров &amp;lt;math&amp;gt;O(C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
* Вычисление решающей функции &amp;lt;math&amp;gt;O(C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
* Обновлене матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;O(C*C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
Общая сложность каждой итерации &amp;lt;math&amp;gt;O(C*C*K)&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;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; параллельных операций, каждая их которых в свою очередь состоит из &amp;lt;math&amp;gt;K&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;C*K&amp;lt;/math&amp;gt; параллельных операций.&lt;br /&gt;
Результатом его работы является значение решающей функции &amp;lt;math&amp;gt;J&amp;lt;/math&amp;gt;. Её значение определяет необходимость завершения алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Третий ярус&#039;&#039;&#039; включает &amp;lt;math&amp;gt;C*K&amp;lt;/math&amp;gt; параллельных операций, каждая из которых состоит из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; параллельных операций, и одной, которая выполняется с использованием результата предыдущих.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Суперпрак.png|1200px|thumb|center|Рисунок 1 Информационный граф алгоритма. Салатовым цветом обозначены вершины графа-операции. Дугами обозначена передача информации, передаваемые данные надписаны сверху.]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
На каждом шаге алгоритма необходимо вычислять сумму элементов массивов. Будем считать, что количество процессоров у нас стремится к бесконечности. Поэтому каждую операцию умножения и деления на данном шаге можно выполнять отдельно, сложность будет составлять только суммирование полученных результатов. Для суммирования применим каскадную схему. &lt;br /&gt;
&lt;br /&gt;
Сложность ее вычисления на первом шаге (вычисление центров кластеров) при параллельной реализации составляет &amp;lt;math&amp;gt;O(\log_{2}N*C)&amp;lt;/math&amp;gt;. Для каждого элемента из набора входных данных(&amp;lt;math&amp;gt; K * N &amp;lt;/math&amp;gt;). Здесь возможен независимый расчет(координатный параллелизм). &lt;br /&gt;
&lt;br /&gt;
На втором шаге(вычисление решающей функции) так же основной сложностью, исходя из начального предположения, является суммирование. Её сложность будет &amp;lt;math&amp;gt;O(\log_{2} {N*C*K})&amp;lt;/math&amp;gt;, потому что здесь необходимо сложение всех элементов. &lt;br /&gt;
&lt;br /&gt;
На третьем шаге имеем сложность &amp;lt;math&amp;gt;O(\log_{2} N*K*C^2)&amp;lt;/math&amp;gt;. Что видно из последовательной реализации в п.1.5.&lt;br /&gt;
&lt;br /&gt;
Итого суммарная сложность итерации: &amp;lt;math&amp;gt;O(\log_{2} {C*K*N} + \log_{2} K^2N^2*C^3)&amp;lt;/math&amp;gt;. Воспользовавшись свойствами логарифма произведения получаем: &amp;lt;math&amp;gt;O(\log_{2} {K^3*N^3} + \log_{2} C^4)&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Скошенного параллелизма в алгоритме нет.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Входные данные:&lt;br /&gt;
* &amp;lt;math&amp;gt;u_{k} ~k = 1, ..., K&amp;lt;/math&amp;gt; - набор входных векторов размерности &amp;lt;math&amp;gt; N &amp;lt;/math&amp;gt;;&lt;br /&gt;
* &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; - количество кластеров;&lt;br /&gt;
* &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость;&lt;br /&gt;
* &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0, ~\delta &amp;gt; 0&amp;lt;/math&amp;gt; - коэффициенты, описывающие точность алгоритма.&lt;br /&gt;
Объем входных данных: &amp;lt;math&amp;gt; K*N &amp;lt;/math&amp;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; C*K &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
*Соотношение последовательной и параллельной сложности алгоритма: &amp;lt;math&amp;gt;C*C*K \over {\log_{2} {K} + \log_{2} C^4}&amp;lt;/math&amp;gt;. Соответственно при распараллеливании наибольший прирост в производительности мы получим при разбиении большого набора данных на большее число кластеров;&lt;br /&gt;
*Вычислительная мощность: &amp;lt;math&amp;gt;{{C^2*K} \over {C*K}} = C&amp;lt;/math&amp;gt;. Получается, что на чем большее количество кластеров мы разбиваем набор данных, тем менее затратным становится перемещение данных;&lt;br /&gt;
*Алгоритм не является устойчивым, как и другие подобные алгоритмы этого класса(например k-means). Очень многое зависит как от входных данных, так и от изначальных параметров приближения(заполнения матрицы принадлежности =&amp;gt; исходных центров кластеров);&lt;br /&gt;
*Не является детерминированным. Так же очень многое зависит как от входных данных, так и от изначальных параметров приближения(заполнения матрицы принадлежности =&amp;gt; исходных центров кластеров);&lt;br /&gt;
*Алгоритм не сбалансирован - доминирует операция умножения. Параллельные ветви алгоритма сбалансированы;&lt;br /&gt;
*Степень исхода вершины информационного графа - 2.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
Проведём исследование масштабируемости параллельной реализации разложения Холецкого согласно [[Scalability methodology|методике]]. Исследование проводилось на суперкомпьютере &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;
&lt;br /&gt;
Набор и границы значений изменяемых [[Глоссарий#Параметры запуска|параметров запуска]] реализации алгоритма: &lt;br /&gt;
&lt;br /&gt;
*	число процессоров [1 : 120];&lt;br /&gt;
*	размер входных данных  [1 : 15 000] векторов размерности 4.&lt;br /&gt;
При количестве кластеров 100.&lt;br /&gt;
&lt;br /&gt;
В результате проведённых экспериментов был получен следующий диапазон [[Глоссарий#Эффективность реализации|эффективности реализации]] алгоритма:&lt;br /&gt;
&lt;br /&gt;
*	минимальная эффективность реализации 0,63%;&lt;br /&gt;
*	максимальная эффективность реализации 2,56%.&lt;br /&gt;
&lt;br /&gt;
В параллельной реализации использовалась технология OpenMP, для передачи данных данных между потоками использовалась технология MPI. Компилятор GNU(gcc) с флагом -fopenmp. Версия компилятора: gcc version 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC).&lt;br /&gt;
&lt;br /&gt;
На следующих рисунках приведены графики [[Глоссарий#Производительность|производительности]] и  [[Глоссарий#Эффективность реализации|эффективности]] выбранной реализации в зависимости от изменяемых параметров запуска.&lt;br /&gt;
&lt;br /&gt;
[[file: FCM произв.jpg |thumb|center|800px|Рисунок 2 Изменение производительности.]]&lt;br /&gt;
&lt;br /&gt;
[[file: FCM эф.jpg |thumb|center|800px|Рисунок 3 Изменение эффективности.]]&lt;br /&gt;
&lt;br /&gt;
Оценки масштабируемости:&lt;br /&gt;
*	По числу процессов: 0.1245. &lt;br /&gt;
*	По размеру задачи: -0.0278. &lt;br /&gt;
*	По двум направлениям: 0,00009.&lt;br /&gt;
&lt;br /&gt;
[http://pastebin.com/LDPNY5Ua Параллельная реализация на языке С с использованием Open MP]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Можно найти следующие реализации алгоритма&lt;br /&gt;
* Для MATLAB http://www.mathworks.com/help/fuzzy/fcm.html &lt;br /&gt;
* В PostgreSQL http://num-meth.srcc.msu.ru/zhurnal/tom_2012/v13r207.html&lt;br /&gt;
Так же готовые реализации алгоритма и его описание можно найти на сайтах&lt;br /&gt;
* https://habrahabr.ru/post/208496/&lt;br /&gt;
* http://pythonhosted.org/scikit-fuzzy/auto_examples/plot_cmeans.html&lt;br /&gt;
* http://www.codeproject.com/Articles/91675/Computer-Vision-Applications-with-C-Fuzzy-C-means&lt;br /&gt;
* https://github.com/gyaikhom/fcm&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>ADovganich</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=21440</id>
		<title>Участник:ADovganich/Нечеткий алгоритм С средних</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=21440"/>
		<updated>2016-12-19T23:51:03Z</updated>

		<summary type="html">&lt;p&gt;ADovganich: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|ASA}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(C*C*K*N*I)&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;K*N&amp;lt;/math&amp;gt;, [количество векторов * размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;C*K&amp;lt;/math&amp;gt;, [элементы матрицы принадлежности]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;3I&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;C*C*K&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Protsenko|Мария Проценко]] (1.5-1.8, 2.7), [[Участник:ADovganich|Андрей Довганич]] (1.1-1.4, 1.9, 1.10)&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Нечеткий алгоритм C-средних (fuzzy C-means) позволяет разбить имеющееся множество векторов (точек) мощностью &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; на заданное число нечетких множеств. Предназначен для кластеризации больших наборов данных. Основным достоинством алгоритма является нечеткость при определении объекта в кластер. Благодаря этому становится возможным определить объекты, которые находятся на границе, в кластеры. Из основного достоинства следует и главный недостаток - неопределенность с объектами, удаленными от центров всех кластеров. В остальном ему присущи стандартные проблемы подобного класса алгоритмов: вычислительная сложность, необходимость задания количества кластеров&amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм был разработан J.C. Dunn в 1973 г.&amp;lt;ref&amp;gt; Dunn, J. C. (1973-01-01). &amp;quot;A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters&amp;quot;. Journal of Cybernetics. 3 (3): 32–57. doi:10.1080/01969727308546046. ISSN 0022-0280.&amp;lt;/ref&amp;gt;, усовершенствован J.C. Bezdek в 1981 г.&amp;lt;ref&amp;gt; Bezdek, James C. (1981). Pattern Recognition with Fuzzy Objective Function Algorithms. ISBN 0-306-40671-3.&amp;lt;/ref&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;
# Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим матрицу &amp;lt;math&amp;gt; M = m_{ik} \in[0,1],\;  i = 1, ..., c, \; k = 1, ..., K &amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;m_{i,k}&amp;lt;/math&amp;gt; - вероятность принадлежности объекта &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; - количество векторов. При этом элементы матрицы удовлетворяют следующим условиям:&lt;br /&gt;
&lt;br /&gt;
* сумма элементов в каждом столбце равна &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* сумма всех элементов матрицы равно &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Назовем &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; матрицей принадлежности.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; - центры кластеров. Тогда рассмотрим функцию &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
J(M, c_{1}, c_{2},...c_{c}) = \sum_{i = 1}^{c}{J_{i}} = \sum_{i = 1}^{c}\sum_{k = 1}^{K}{m_{ik}^q}d_{ik}^2 ~(1)&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt; d_{ik} = \left\Vert{u_{k}-c_{i}}\right\| &amp;lt;/math&amp;gt; - Евклидово расстояние между центром кластера и объектом, &amp;lt;math&amp;gt; 1 \le q \le \infty &amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость. Будем минимизировать значение функции &amp;lt;math&amp;gt; J &amp;lt;/math&amp;gt;. Для этого вычислим центры кластеров по формуле &amp;lt;math&amp;gt; ~(2) &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c_{i} = {{\sum_{k = 1}^{K}{m_{ik}^q} * u_{k}} \over {\sum_{k = 1}^{K}{m_{ik}^q}}}~(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;m_{ik}&amp;lt;/math&amp;gt; — коэффициент принадлежности &amp;lt;math&amp;gt;u_{k}&amp;lt;/math&amp;gt; вектора к кластеру &amp;lt;math&amp;gt;c_{i}&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
и новые значения матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; по формуле &amp;lt;math&amp;gt; ~(3) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;m_{ik} = {1 \over \sum_{j = 1}^{c}{({{d_{ik}} \over {d_{jk}}})}^{2 \over q-1}} ~(3)&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; ~(2) &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; ~(3) &amp;lt;/math&amp;gt;являются необходимым условиями достижения минимума функцией &amp;lt;math&amp;gt; J &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; случайными значениями от 0 до 1;&lt;br /&gt;
# Вычислить центры кластеров &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; используя формулу &amp;lt;math&amp;gt;~(2)&amp;lt;/math&amp;gt;;&lt;br /&gt;
# Вычислить значение решающей функции по формуле &amp;lt;math&amp;gt;~(1)&amp;lt;/math&amp;gt;. Если значение &amp;lt;math&amp;gt; J &amp;lt; \varepsilon,~\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt; |J_{i} - J_{i-1}| &amp;lt; \delta,~\delta &amp;gt; 0 &amp;lt;/math&amp;gt;, то остановить вычисления;&lt;br /&gt;
# Иначе вычислить новые значения матрицы М по формуле &amp;lt;math&amp;gt;~(3)&amp;lt;/math&amp;gt;;&lt;br /&gt;
# Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительным ядром алгоритма являются формулы: &amp;lt;math&amp;gt; (1) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (2) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (3) &amp;lt;/math&amp;gt;. В них производится вычисление новых центров кластеров, значения решающей функции и пересчет элементов матрицы принадлежности.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Макроструктура алгоритма состоит из следующих шагов:&lt;br /&gt;
&lt;br /&gt;
# Инициализация матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; случайными значениями от 0 до 1;&lt;br /&gt;
# Вычисление центров кластеров; &lt;br /&gt;
# Вычисление значения решающей функции(если оно удовлетворяет условиям останова - завершение вычислений);&lt;br /&gt;
# Вычисление новых элементов матрицы принадлежности;&lt;br /&gt;
# Переход к шагу 2;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации алгоритма на языке С++. Сначала вычислим центры кластеров, потом вычислим решающую функцию, с ее помощью определим необходимость продолжать алгоритм, и при необходимости вычислим новые значения матрицы M.&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    float ** m;&lt;br /&gt;
    int *c;&lt;br /&gt;
    int number_clusters, number_items;&lt;br /&gt;
    m = gen_random_clusters();//заполним матрицу m случайными значениями от 0 до 1&lt;br /&gt;
    &lt;br /&gt;
    while (true)&lt;br /&gt;
    {&lt;br /&gt;
      //вычисление центров кластеров&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
        {&lt;br /&gt;
            numerator==denumerator=0;&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
            {&lt;br /&gt;
                numerator+=pow(m[i, k], q)*u[k];//u[k]-вектор&lt;br /&gt;
                denumerator+=pow(m[i, k], q);&lt;br /&gt;
            }&lt;br /&gt;
        c[i]= numerator / denumerator;//центры кластеров&lt;br /&gt;
        }&lt;br /&gt;
    &lt;br /&gt;
        j=0;//вычисление решающей функции&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
                j+=pow(m[i, k], q)*pow(dist(c[i], x[k],2);//dist-вычисляет расстояние между заданными векторами&lt;br /&gt;
    &lt;br /&gt;
       if ((abs(j-last_j)&amp;lt;delta) || (j&amp;lt;eps)) break;//проверка на необходимость завернешения алгоритма&lt;br /&gt;
       last_j=j;&lt;br /&gt;
     //обновление матрицы m&lt;br /&gt;
       for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
          for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
             {&lt;br /&gt;
               m[i,k]=0&lt;br /&gt;
              for(int j=0; j&amp;lt;number_clusters; j++)&lt;br /&gt;
                  m[i,k]+=pow(dist(c[i], x[k])/dist(c[j], x[k]),2/(q-1));&lt;br /&gt;
              m[i,k]=1/m[i,k];&lt;br /&gt;
              }&lt;br /&gt;
                                       &lt;br /&gt;
    }&lt;br /&gt;
    &amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Каждая итерация включает в себя&lt;br /&gt;
* Вычисление центров кластеров &amp;lt;math&amp;gt;O(C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
* Вычисление решающей функции &amp;lt;math&amp;gt;O(C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
* Обновлене матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;O(C*C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
Общая сложность каждой итерации &amp;lt;math&amp;gt;O(C*C*K)&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;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; параллельных операций, каждая их которых в свою очередь состоит из &amp;lt;math&amp;gt;K&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;C*K&amp;lt;/math&amp;gt; параллельных операций.&lt;br /&gt;
Результатом его работы является значение решающей функции &amp;lt;math&amp;gt;J&amp;lt;/math&amp;gt;. Её значение определяет необходимость завершения алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Третий ярус&#039;&#039;&#039; включает &amp;lt;math&amp;gt;C*K&amp;lt;/math&amp;gt; параллельных операций, каждая из которых состоит из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; параллельных операций, и одной, которая выполняется с использованием результата предыдущих.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Суперпрак.png|1200px|thumb|center|Рисунок 1 Информационный граф алгоритма. Салатовым цветом обозначены вершины графа-операции. Дугами обозначена передача информации, передаваемые данные надписаны сверху.]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
На каждом шаге алгоритма необходимо вычислять сумму элементов массивов. Будем считать, что количество процессоров у нас стремится к бесконечности. Поэтому каждую операцию умножения и деления на данном шаге можно выполнять отдельно, сложность будет составлять только суммирование, полученных результатов. Для суммирования применим каскадную схему. &lt;br /&gt;
&lt;br /&gt;
Сложность ее вычисления на первом шаге (вычисление центров кластеров) при параллельной реализации составляет &amp;lt;math&amp;gt;O(\log_{2}N*C)&amp;lt;/math&amp;gt;. Для каждого элемента из набора входных данных(&amp;lt;math&amp;gt; K * N &amp;lt;/math&amp;gt;). Здесь возможен независимый расчет(координатный параллелизм). &lt;br /&gt;
&lt;br /&gt;
На втором шаге(вычисление решающей функции) так же основной сложностью, исходя из начального предположения, является суммирование. Её сложность будет &amp;lt;math&amp;gt;O(\log_{2} {N*C*K})&amp;lt;/math&amp;gt;, потому что здесь необходимо сложение всех элементов. &lt;br /&gt;
&lt;br /&gt;
На третьем шаге имеем сложность &amp;lt;math&amp;gt;O(\log_{2} N*K*C^2)&amp;lt;/math&amp;gt;. Что видно из последовательной реализации в п.1.5.&lt;br /&gt;
&lt;br /&gt;
Итого суммарная сложность итерации: &amp;lt;math&amp;gt;O(\log_{2} {C*K*N} + \log_{2} K^2N^2*C^3)&amp;lt;/math&amp;gt;. Воспользовавшись свойствами логарифма произведения получаем: &amp;lt;math&amp;gt;O(\log_{2} {K^3*N^3} + \log_{2} C^4)&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Скошенного параллелизма в алгоритме нет.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Входные данные:&lt;br /&gt;
* &amp;lt;math&amp;gt;u_{k} ~k = 1, ..., K&amp;lt;/math&amp;gt; - набор входных векторов размерности &amp;lt;math&amp;gt; N &amp;lt;/math&amp;gt;;&lt;br /&gt;
* &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; - количество кластеров;&lt;br /&gt;
* &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость;&lt;br /&gt;
* &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0, ~\delta &amp;gt; 0&amp;lt;/math&amp;gt; - коэффициенты, описывающие точность алгоритма.&lt;br /&gt;
Объем входных данных: &amp;lt;math&amp;gt; K*N &amp;lt;/math&amp;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; C*K &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
*Соотношение последовательной и параллельной сложности алгоритма: &amp;lt;math&amp;gt;C*C*K \over {\log_{2} {K} + \log_{2} C^4}&amp;lt;/math&amp;gt;. Соответственно при распараллеливании наибольший прирост в производительности мы получим при разбиении большого набора данных на большее число кластеров;&lt;br /&gt;
*Вычислительная мощность: &amp;lt;math&amp;gt;{{C^2*K} \over {C*K}} = C&amp;lt;/math&amp;gt;. Получается, что на чем большее количество кластеров мы разбиваем набор данных, тем менее затратным становится перемещение данных;&lt;br /&gt;
*Алгоритм не является устойчивым, как и другие подобные алгоритмы этого класса(например k-means). Очень многое зависит как от входных данных, так и от изначальных параметров приближения(заполнения матрицы принадлежности =&amp;gt; исходных центров кластеров);&lt;br /&gt;
*Не является детерминированным. Так же очень многое зависит как от входных данных, так и от изначальных параметров приближения(заполнения матрицы принадлежности =&amp;gt; исходных центров кластеров);&lt;br /&gt;
*Алгоритм не сбалансирован - доминирует операция умножения. Параллельные ветви алгоритма сбалансированы;&lt;br /&gt;
*Степень исхода вершины информационного графа - 2.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
Проведём исследование масштабируемости параллельной реализации разложения Холецкого согласно [[Scalability methodology|методике]]. Исследование проводилось на суперкомпьютере &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;
&lt;br /&gt;
Набор и границы значений изменяемых [[Глоссарий#Параметры запуска|параметров запуска]] реализации алгоритма: &lt;br /&gt;
&lt;br /&gt;
*	число процессоров [1 : 120];&lt;br /&gt;
*	размер входных данных  [1 : 15 000] векторов размерности 4.&lt;br /&gt;
При количестве кластеров 100.&lt;br /&gt;
&lt;br /&gt;
В результате проведённых экспериментов был получен следующий диапазон [[Глоссарий#Эффективность реализации|эффективности реализации]] алгоритма:&lt;br /&gt;
&lt;br /&gt;
*	минимальная эффективность реализации 0,63%;&lt;br /&gt;
*	максимальная эффективность реализации 2,56%.&lt;br /&gt;
&lt;br /&gt;
В параллельной реализации использовалась технология OpenMP, для передачи данных данных между потоками использовалась технология MPI. Компилятор GNU(gcc) с флагом -fopenmp. Версия компилятора: gcc version 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC).&lt;br /&gt;
&lt;br /&gt;
На следующих рисунках приведены графики [[Глоссарий#Производительность|производительности]] и  [[Глоссарий#Эффективность реализации|эффективности]] выбранной реализации в зависимости от изменяемых параметров запуска.&lt;br /&gt;
&lt;br /&gt;
[[file: FCM произв.jpg |thumb|center|800px|Рисунок 2 Изменение производительности.]]&lt;br /&gt;
&lt;br /&gt;
[[file: FCM эф.jpg |thumb|center|800px|Рисунок 3 Изменение эффективности.]]&lt;br /&gt;
&lt;br /&gt;
Оценки масштабируемости:&lt;br /&gt;
*	По числу процессов: 0.1245. &lt;br /&gt;
*	По размеру задачи: -0.0278. &lt;br /&gt;
*	По двум направлениям: 0,00009.&lt;br /&gt;
&lt;br /&gt;
[http://pastebin.com/LDPNY5Ua Параллельная реализация на языке С с использованием Open MP]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Можно найти следующие реализации алгоритма&lt;br /&gt;
* Для MATLAB http://www.mathworks.com/help/fuzzy/fcm.html &lt;br /&gt;
* В PostgreSQL http://num-meth.srcc.msu.ru/zhurnal/tom_2012/v13r207.html&lt;br /&gt;
Так же готовые реализации алгоритма и его описание можно найти на сайтах&lt;br /&gt;
* https://habrahabr.ru/post/208496/&lt;br /&gt;
* http://pythonhosted.org/scikit-fuzzy/auto_examples/plot_cmeans.html&lt;br /&gt;
* http://www.codeproject.com/Articles/91675/Computer-Vision-Applications-with-C-Fuzzy-C-means&lt;br /&gt;
* https://github.com/gyaikhom/fcm&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>ADovganich</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=21439</id>
		<title>Участник:ADovganich/Нечеткий алгоритм С средних</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=21439"/>
		<updated>2016-12-19T23:49:34Z</updated>

		<summary type="html">&lt;p&gt;ADovganich: /* Ресурс параллелизма алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|ASA}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(C*C*K*I)&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;K*N&amp;lt;/math&amp;gt;, [количество векторов * размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;C*K&amp;lt;/math&amp;gt;, [элементы матрицы принадлежности]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;3I&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;C*C*K&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Protsenko|Мария Проценко]] (1.5-1.8, 2.7), [[Участник:ADovganich|Андрей Довганич]] (1.1-1.4, 1.9, 1.10)&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Нечеткий алгоритм C-средних (fuzzy C-means) позволяет разбить имеющееся множество векторов (точек) мощностью &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; на заданное число нечетких множеств. Предназначен для кластеризации больших наборов данных. Основным достоинством алгоритма является нечеткость при определении объекта в кластер. Благодаря этому становится возможным определить объекты, которые находятся на границе, в кластеры. Из основного достоинства следует и главный недостаток - неопределенность с объектами, удаленными от центров всех кластеров. В остальном ему присущи стандартные проблемы подобного класса алгоритмов: вычислительная сложность, необходимость задания количества кластеров&amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм был разработан J.C. Dunn в 1973 г.&amp;lt;ref&amp;gt; Dunn, J. C. (1973-01-01). &amp;quot;A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters&amp;quot;. Journal of Cybernetics. 3 (3): 32–57. doi:10.1080/01969727308546046. ISSN 0022-0280.&amp;lt;/ref&amp;gt;, усовершенствован J.C. Bezdek в 1981 г.&amp;lt;ref&amp;gt; Bezdek, James C. (1981). Pattern Recognition with Fuzzy Objective Function Algorithms. ISBN 0-306-40671-3.&amp;lt;/ref&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;
# Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим матрицу &amp;lt;math&amp;gt; M = m_{ik} \in[0,1],\;  i = 1, ..., c, \; k = 1, ..., K &amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;m_{i,k}&amp;lt;/math&amp;gt; - вероятность принадлежности объекта &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; - количество векторов. При этом элементы матрицы удовлетворяют следующим условиям:&lt;br /&gt;
&lt;br /&gt;
* сумма элементов в каждом столбце равна &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* сумма всех элементов матрицы равно &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Назовем &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; матрицей принадлежности.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; - центры кластеров. Тогда рассмотрим функцию &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
J(M, c_{1}, c_{2},...c_{c}) = \sum_{i = 1}^{c}{J_{i}} = \sum_{i = 1}^{c}\sum_{k = 1}^{K}{m_{ik}^q}d_{ik}^2 ~(1)&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt; d_{ik} = \left\Vert{u_{k}-c_{i}}\right\| &amp;lt;/math&amp;gt; - Евклидово расстояние между центром кластера и объектом, &amp;lt;math&amp;gt; 1 \le q \le \infty &amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость. Будем минимизировать значение функции &amp;lt;math&amp;gt; J &amp;lt;/math&amp;gt;. Для этого вычислим центры кластеров по формуле &amp;lt;math&amp;gt; ~(2) &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c_{i} = {{\sum_{k = 1}^{K}{m_{ik}^q} * u_{k}} \over {\sum_{k = 1}^{K}{m_{ik}^q}}}~(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;m_{ik}&amp;lt;/math&amp;gt; — коэффициент принадлежности &amp;lt;math&amp;gt;u_{k}&amp;lt;/math&amp;gt; вектора к кластеру &amp;lt;math&amp;gt;c_{i}&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
и новые значения матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; по формуле &amp;lt;math&amp;gt; ~(3) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;m_{ik} = {1 \over \sum_{j = 1}^{c}{({{d_{ik}} \over {d_{jk}}})}^{2 \over q-1}} ~(3)&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; ~(2) &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; ~(3) &amp;lt;/math&amp;gt;являются необходимым условиями достижения минимума функцией &amp;lt;math&amp;gt; J &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; случайными значениями от 0 до 1;&lt;br /&gt;
# Вычислить центры кластеров &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; используя формулу &amp;lt;math&amp;gt;~(2)&amp;lt;/math&amp;gt;;&lt;br /&gt;
# Вычислить значение решающей функции по формуле &amp;lt;math&amp;gt;~(1)&amp;lt;/math&amp;gt;. Если значение &amp;lt;math&amp;gt; J &amp;lt; \varepsilon,~\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt; |J_{i} - J_{i-1}| &amp;lt; \delta,~\delta &amp;gt; 0 &amp;lt;/math&amp;gt;, то остановить вычисления;&lt;br /&gt;
# Иначе вычислить новые значения матрицы М по формуле &amp;lt;math&amp;gt;~(3)&amp;lt;/math&amp;gt;;&lt;br /&gt;
# Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительным ядром алгоритма являются формулы: &amp;lt;math&amp;gt; (1) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (2) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (3) &amp;lt;/math&amp;gt;. В них производится вычисление новых центров кластеров, значения решающей функции и пересчет элементов матрицы принадлежности.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Макроструктура алгоритма состоит из следующих шагов:&lt;br /&gt;
&lt;br /&gt;
# Инициализация матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; случайными значениями от 0 до 1;&lt;br /&gt;
# Вычисление центров кластеров; &lt;br /&gt;
# Вычисление значения решающей функции(если оно удовлетворяет условиям останова - завершение вычислений);&lt;br /&gt;
# Вычисление новых элементов матрицы принадлежности;&lt;br /&gt;
# Переход к шагу 2;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации алгоритма на языке С++. Сначала вычислим центры кластеров, потом вычислим решающую функцию, с ее помощью определим необходимость продолжать алгоритм, и при необходимости вычислим новые значения матрицы M.&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    float ** m;&lt;br /&gt;
    int *c;&lt;br /&gt;
    int number_clusters, number_items;&lt;br /&gt;
    m = gen_random_clusters();//заполним матрицу m случайными значениями от 0 до 1&lt;br /&gt;
    &lt;br /&gt;
    while (true)&lt;br /&gt;
    {&lt;br /&gt;
      //вычисление центров кластеров&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
        {&lt;br /&gt;
            numerator==denumerator=0;&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
            {&lt;br /&gt;
                numerator+=pow(m[i, k], q)*u[k];//u[k]-вектор&lt;br /&gt;
                denumerator+=pow(m[i, k], q);&lt;br /&gt;
            }&lt;br /&gt;
        c[i]= numerator / denumerator;//центры кластеров&lt;br /&gt;
        }&lt;br /&gt;
    &lt;br /&gt;
        j=0;//вычисление решающей функции&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
                j+=pow(m[i, k], q)*pow(dist(c[i], x[k],2);//dist-вычисляет расстояние между заданными векторами&lt;br /&gt;
    &lt;br /&gt;
       if ((abs(j-last_j)&amp;lt;delta) || (j&amp;lt;eps)) break;//проверка на необходимость завернешения алгоритма&lt;br /&gt;
       last_j=j;&lt;br /&gt;
     //обновление матрицы m&lt;br /&gt;
       for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
          for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
             {&lt;br /&gt;
               m[i,k]=0&lt;br /&gt;
              for(int j=0; j&amp;lt;number_clusters; j++)&lt;br /&gt;
                  m[i,k]+=pow(dist(c[i], x[k])/dist(c[j], x[k]),2/(q-1));&lt;br /&gt;
              m[i,k]=1/m[i,k];&lt;br /&gt;
              }&lt;br /&gt;
                                       &lt;br /&gt;
    }&lt;br /&gt;
    &amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Каждая итерация включает в себя&lt;br /&gt;
* Вычисление центров кластеров &amp;lt;math&amp;gt;O(C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
* Вычисление решающей функции &amp;lt;math&amp;gt;O(C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
* Обновлене матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;O(C*C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
Общая сложность каждой итерации &amp;lt;math&amp;gt;O(C*C*K)&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;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; параллельных операций, каждая их которых в свою очередь состоит из &amp;lt;math&amp;gt;K&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;C*K&amp;lt;/math&amp;gt; параллельных операций.&lt;br /&gt;
Результатом его работы является значение решающей функции &amp;lt;math&amp;gt;J&amp;lt;/math&amp;gt;. Её значение определяет необходимость завершения алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Третий ярус&#039;&#039;&#039; включает &amp;lt;math&amp;gt;C*K&amp;lt;/math&amp;gt; параллельных операций, каждая из которых состоит из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; параллельных операций, и одной, которая выполняется с использованием результата предыдущих.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Суперпрак.png|1200px|thumb|center|Рисунок 1 Информационный граф алгоритма. Салатовым цветом обозначены вершины графа-операции. Дугами обозначена передача информации, передаваемые данные надписаны сверху.]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
На каждом шаге алгоритма необходимо вычислять сумму элементов массивов. Будем считать, что количество процессоров у нас стремится к бесконечности. Поэтому каждую операцию умножения и деления на данном шаге можно выполнять отдельно, сложность будет составлять только суммирование, полученных результатов. Для суммирования применим каскадную схему. &lt;br /&gt;
&lt;br /&gt;
Сложность ее вычисления на первом шаге (вычисление центров кластеров) при параллельной реализации составляет &amp;lt;math&amp;gt;O(\log_{2}N*C)&amp;lt;/math&amp;gt;. Для каждого элемента из набора входных данных(&amp;lt;math&amp;gt; K * N &amp;lt;/math&amp;gt;). Здесь возможен независимый расчет(координатный параллелизм). &lt;br /&gt;
&lt;br /&gt;
На втором шаге(вычисление решающей функции) так же основной сложностью, исходя из начального предположения, является суммирование. Её сложность будет &amp;lt;math&amp;gt;O(\log_{2} {N*C*K})&amp;lt;/math&amp;gt;, потому что здесь необходимо сложение всех элементов. &lt;br /&gt;
&lt;br /&gt;
На третьем шаге имеем сложность &amp;lt;math&amp;gt;O(\log_{2} N*K*C^2)&amp;lt;/math&amp;gt;. Что видно из последовательной реализации в п.1.5.&lt;br /&gt;
&lt;br /&gt;
Итого суммарная сложность итерации: &amp;lt;math&amp;gt;O(\log_{2} {C*K*N} + \log_{2} K^2N^2*C^3)&amp;lt;/math&amp;gt;. Воспользовавшись свойствами логарифма произведения получаем: &amp;lt;math&amp;gt;O(\log_{2} {K^3*N^3} + \log_{2} C^4)&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Скошенного параллелизма в алгоритме нет.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Входные данные:&lt;br /&gt;
* &amp;lt;math&amp;gt;u_{k} ~k = 1, ..., K&amp;lt;/math&amp;gt; - набор входных векторов размерности &amp;lt;math&amp;gt; N &amp;lt;/math&amp;gt;;&lt;br /&gt;
* &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; - количество кластеров;&lt;br /&gt;
* &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость;&lt;br /&gt;
* &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0, ~\delta &amp;gt; 0&amp;lt;/math&amp;gt; - коэффициенты, описывающие точность алгоритма.&lt;br /&gt;
Объем входных данных: &amp;lt;math&amp;gt; K*N &amp;lt;/math&amp;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; C*K &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
*Соотношение последовательной и параллельной сложности алгоритма: &amp;lt;math&amp;gt;C*C*K \over {\log_{2} {K} + \log_{2} C^4}&amp;lt;/math&amp;gt;. Соответственно при распараллеливании наибольший прирост в производительности мы получим при разбиении большого набора данных на большее число кластеров;&lt;br /&gt;
*Вычислительная мощность: &amp;lt;math&amp;gt;{{C^2*K} \over {C*K}} = C&amp;lt;/math&amp;gt;. Получается, что на чем большее количество кластеров мы разбиваем набор данных, тем менее затратным становится перемещение данных;&lt;br /&gt;
*Алгоритм не является устойчивым, как и другие подобные алгоритмы этого класса(например k-means). Очень многое зависит как от входных данных, так и от изначальных параметров приближения(заполнения матрицы принадлежности =&amp;gt; исходных центров кластеров);&lt;br /&gt;
*Не является детерминированным. Так же очень многое зависит как от входных данных, так и от изначальных параметров приближения(заполнения матрицы принадлежности =&amp;gt; исходных центров кластеров);&lt;br /&gt;
*Алгоритм не сбалансирован - доминирует операция умножения. Параллельные ветви алгоритма сбалансированы;&lt;br /&gt;
*Степень исхода вершины информационного графа - 2.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
Проведём исследование масштабируемости параллельной реализации разложения Холецкого согласно [[Scalability methodology|методике]]. Исследование проводилось на суперкомпьютере &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;
&lt;br /&gt;
Набор и границы значений изменяемых [[Глоссарий#Параметры запуска|параметров запуска]] реализации алгоритма: &lt;br /&gt;
&lt;br /&gt;
*	число процессоров [1 : 120];&lt;br /&gt;
*	размер входных данных  [1 : 15 000] векторов размерности 4.&lt;br /&gt;
При количестве кластеров 100.&lt;br /&gt;
&lt;br /&gt;
В результате проведённых экспериментов был получен следующий диапазон [[Глоссарий#Эффективность реализации|эффективности реализации]] алгоритма:&lt;br /&gt;
&lt;br /&gt;
*	минимальная эффективность реализации 0,63%;&lt;br /&gt;
*	максимальная эффективность реализации 2,56%.&lt;br /&gt;
&lt;br /&gt;
В параллельной реализации использовалась технология OpenMP, для передачи данных данных между потоками использовалась технология MPI. Компилятор GNU(gcc) с флагом -fopenmp. Версия компилятора: gcc version 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC).&lt;br /&gt;
&lt;br /&gt;
На следующих рисунках приведены графики [[Глоссарий#Производительность|производительности]] и  [[Глоссарий#Эффективность реализации|эффективности]] выбранной реализации в зависимости от изменяемых параметров запуска.&lt;br /&gt;
&lt;br /&gt;
[[file: FCM произв.jpg |thumb|center|800px|Рисунок 2 Изменение производительности.]]&lt;br /&gt;
&lt;br /&gt;
[[file: FCM эф.jpg |thumb|center|800px|Рисунок 3 Изменение эффективности.]]&lt;br /&gt;
&lt;br /&gt;
Оценки масштабируемости:&lt;br /&gt;
*	По числу процессов: 0.1245. &lt;br /&gt;
*	По размеру задачи: -0.0278. &lt;br /&gt;
*	По двум направлениям: 0,00009.&lt;br /&gt;
&lt;br /&gt;
[http://pastebin.com/LDPNY5Ua Параллельная реализация на языке С с использованием Open MP]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Можно найти следующие реализации алгоритма&lt;br /&gt;
* Для MATLAB http://www.mathworks.com/help/fuzzy/fcm.html &lt;br /&gt;
* В PostgreSQL http://num-meth.srcc.msu.ru/zhurnal/tom_2012/v13r207.html&lt;br /&gt;
Так же готовые реализации алгоритма и его описание можно найти на сайтах&lt;br /&gt;
* https://habrahabr.ru/post/208496/&lt;br /&gt;
* http://pythonhosted.org/scikit-fuzzy/auto_examples/plot_cmeans.html&lt;br /&gt;
* http://www.codeproject.com/Articles/91675/Computer-Vision-Applications-with-C-Fuzzy-C-means&lt;br /&gt;
* https://github.com/gyaikhom/fcm&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>ADovganich</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=21437</id>
		<title>Участник:ADovganich/Нечеткий алгоритм С средних</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=21437"/>
		<updated>2016-12-19T22:52:09Z</updated>

		<summary type="html">&lt;p&gt;ADovganich: /* Ресурс параллелизма алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|ASA}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(C*C*K*I)&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;K*N&amp;lt;/math&amp;gt;, [количество векторов * размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;C*K&amp;lt;/math&amp;gt;, [элементы матрицы принадлежности]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;3I&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;C*C*K&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Protsenko|Мария Проценко]] (1.5-1.8, 2.7), [[Участник:ADovganich|Андрей Довганич]] (1.1-1.4, 1.9, 1.10)&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Нечеткий алгоритм C-средних (fuzzy C-means) позволяет разбить имеющееся множество векторов (точек) мощностью &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; на заданное число нечетких множеств. Предназначен для кластеризации больших наборов данных. Основным достоинством алгоритма является нечеткость при определении объекта в кластер. Благодаря этому становится возможным определить объекты, которые находятся на границе, в кластеры. Из основного достоинства следует и главный недостаток - неопределенность с объектами, удаленными от центров всех кластеров. В остальном ему присущи стандартные проблемы подобного класса алгоритмов: вычислительная сложность, необходимость задания количества кластеров&amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм был разработан J.C. Dunn в 1973 г.&amp;lt;ref&amp;gt; Dunn, J. C. (1973-01-01). &amp;quot;A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters&amp;quot;. Journal of Cybernetics. 3 (3): 32–57. doi:10.1080/01969727308546046. ISSN 0022-0280.&amp;lt;/ref&amp;gt;, усовершенствован J.C. Bezdek в 1981 г.&amp;lt;ref&amp;gt; Bezdek, James C. (1981). Pattern Recognition with Fuzzy Objective Function Algorithms. ISBN 0-306-40671-3.&amp;lt;/ref&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;
# Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим матрицу &amp;lt;math&amp;gt; M = m_{ik} \in[0,1],\;  i = 1, ..., c, \; k = 1, ..., K &amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;m_{i,k}&amp;lt;/math&amp;gt; - вероятность принадлежности объекта &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; - количество векторов. При этом элементы матрицы удовлетворяют следующим условиям:&lt;br /&gt;
&lt;br /&gt;
* сумма элементов в каждом столбце равна &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* сумма всех элементов матрицы равно &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Назовем &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; матрицей принадлежности.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; - центры кластеров. Тогда рассмотрим функцию &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
J(M, c_{1}, c_{2},...c_{c}) = \sum_{i = 1}^{c}{J_{i}} = \sum_{i = 1}^{c}\sum_{k = 1}^{K}{m_{ik}^q}d_{ik}^2 ~(1)&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt; d_{ik} = \left\Vert{u_{k}-c_{i}}\right\| &amp;lt;/math&amp;gt; - Евклидово расстояние между центром кластера и объектом, &amp;lt;math&amp;gt; 1 \le q \le \infty &amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость. Будем минимизировать значение функции &amp;lt;math&amp;gt; J &amp;lt;/math&amp;gt;. Для этого вычислим центры кластеров по формуле &amp;lt;math&amp;gt; ~(2) &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c_{i} = {{\sum_{k = 1}^{K}{m_{ik}^q} * u_{k}} \over {\sum_{k = 1}^{K}{m_{ik}^q}}}~(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;m_{ik}&amp;lt;/math&amp;gt; — коэффициент принадлежности &amp;lt;math&amp;gt;u_{k}&amp;lt;/math&amp;gt; вектора к кластеру &amp;lt;math&amp;gt;c_{i}&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
и новые значения матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; по формуле &amp;lt;math&amp;gt; ~(3) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;m_{ik} = {1 \over \sum_{j = 1}^{c}{({{d_{ik}} \over {d_{jk}}})}^{2 \over q-1}} ~(3)&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; ~(2) &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; ~(3) &amp;lt;/math&amp;gt;являются необходимым условиями достижения минимума функцией &amp;lt;math&amp;gt; J &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; случайными значениями от 0 до 1;&lt;br /&gt;
# Вычислить центры кластеров &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; используя формулу &amp;lt;math&amp;gt;~(2)&amp;lt;/math&amp;gt;;&lt;br /&gt;
# Вычислить значение решающей функции по формуле &amp;lt;math&amp;gt;~(1)&amp;lt;/math&amp;gt;. Если значение &amp;lt;math&amp;gt; J &amp;lt; \varepsilon,~\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt; |J_{i} - J_{i-1}| &amp;lt; \delta,~\delta &amp;gt; 0 &amp;lt;/math&amp;gt;, то остановить вычисления;&lt;br /&gt;
# Иначе вычислить новые значения матрицы М по формуле &amp;lt;math&amp;gt;~(3)&amp;lt;/math&amp;gt;;&lt;br /&gt;
# Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительным ядром алгоритма являются формулы: &amp;lt;math&amp;gt; (1) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (2) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (3) &amp;lt;/math&amp;gt;. В них производится вычисление новых центров кластеров, значения решающей функции и пересчет элементов матрицы принадлежности.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Макроструктура алгоритма состоит из следующих шагов:&lt;br /&gt;
&lt;br /&gt;
# Инициализация матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; случайными значениями от 0 до 1;&lt;br /&gt;
# Вычисление центров кластеров; &lt;br /&gt;
# Вычисление значения решающей функции(если оно удовлетворяет условиям останова - завершение вычислений);&lt;br /&gt;
# Вычисление новых элементов матрицы принадлежности;&lt;br /&gt;
# Переход к шагу 2;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации алгоритма на языке С++. Сначала вычислим центры кластеров, потом вычислим решающую функцию, с ее помощью определим необходимость продолжать алгоритм, и при необходимости вычислим новые значения матрицы M.&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    float ** m;&lt;br /&gt;
    int *c;&lt;br /&gt;
    int number_clusters, number_items;&lt;br /&gt;
    m = gen_random_clusters();//заполним матрицу m случайными значениями от 0 до 1&lt;br /&gt;
    &lt;br /&gt;
    while (true)&lt;br /&gt;
    {&lt;br /&gt;
      //вычисление центров кластеров&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
        {&lt;br /&gt;
            numerator==denumerator=0;&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
            {&lt;br /&gt;
                numerator+=pow(m[i, k], q)*u[k];//u[k]-вектор&lt;br /&gt;
                denumerator+=pow(m[i, k], q);&lt;br /&gt;
            }&lt;br /&gt;
        c[i]= numerator / denumerator;//центры кластеров&lt;br /&gt;
        }&lt;br /&gt;
    &lt;br /&gt;
        j=0;//вычисление решающей функции&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
                j+=pow(m[i, k], q)*pow(dist(c[i], x[k],2);//dist-вычисляет расстояние между заданными векторами&lt;br /&gt;
    &lt;br /&gt;
       if ((abs(j-last_j)&amp;lt;delta) || (j&amp;lt;eps)) break;//проверка на необходимость завернешения алгоритма&lt;br /&gt;
       last_j=j;&lt;br /&gt;
     //обновление матрицы m&lt;br /&gt;
       for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
          for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
             {&lt;br /&gt;
               m[i,k]=0&lt;br /&gt;
              for(int j=0; j&amp;lt;number_clusters; j++)&lt;br /&gt;
                  m[i,k]+=pow(dist(c[i], x[k])/dist(c[j], x[k]),2/(q-1));&lt;br /&gt;
              m[i,k]=1/m[i,k];&lt;br /&gt;
              }&lt;br /&gt;
                                       &lt;br /&gt;
    }&lt;br /&gt;
    &amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Каждая итерация включает в себя&lt;br /&gt;
* Вычисление центров кластеров &amp;lt;math&amp;gt;O(C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
* Вычисление решающей функции &amp;lt;math&amp;gt;O(C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
* Обновлене матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;O(C*C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
Общая сложность каждой итерации &amp;lt;math&amp;gt;O(C*C*K)&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;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; параллельных операций, каждая их которых в свою очередь состоит из &amp;lt;math&amp;gt;K&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;C*K&amp;lt;/math&amp;gt; параллельных операций.&lt;br /&gt;
Результатом его работы является значение решающей функции &amp;lt;math&amp;gt;J&amp;lt;/math&amp;gt;. Её значение определяет необходимость завершения алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Третий ярус&#039;&#039;&#039; включает &amp;lt;math&amp;gt;C*K&amp;lt;/math&amp;gt; параллельных операций, каждая из которых состоит из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; параллельных операций, и одной, которая выполняется с использованием результата предыдущих.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Суперпрак.png|1200px|thumb|center|Рисунок 1 Информационный граф алгоритма. Салатовым цветом обозначены вершины графа-операции. Дугами обозначена передача информации, передаваемые данные надписаны сверху.]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
На каждом шаге алгоритма необходимо вычислять сумму элементов массивов. Сложность ее вычисления на первом шаге (вычисление центров кластеров) при параллельной реализации составляет &amp;lt;math&amp;gt;O(\log_{2} C)&amp;lt;/math&amp;gt;. Для каждого элемента из набора входных данных(&amp;lt;math&amp;gt; K * N &amp;lt;/math&amp;gt;), но здесь возможен независимый расчет(координатный параллелизм). На втором шаге(вычисление решающей функции) сложность будет &amp;lt;math&amp;gt;O(\log_{2} {C*K*N})&amp;lt;/math&amp;gt;, потому что здесь необходимо сложение всех элементов. На третьем шаге имеем сложность &amp;lt;math&amp;gt;O(\log_{2} C^2)&amp;lt;/math&amp;gt;. Итого суммарная сложность итерации: &amp;lt;math&amp;gt;O(\log_{2} {C*K*N} + \log_{2} C^3)&amp;lt;/math&amp;gt;. Воспользовавшись свойствами логарифма произведения получаем: &amp;lt;math&amp;gt;O(\log_{2} {K*N} + \log_{2} C^4)&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Скошенного параллелизма в алгоритме нет.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Входные данные:&lt;br /&gt;
* &amp;lt;math&amp;gt;u_{k} ~k = 1, ..., K&amp;lt;/math&amp;gt; - набор входных векторов размерности &amp;lt;math&amp;gt; N &amp;lt;/math&amp;gt;;&lt;br /&gt;
* &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; - количество кластеров;&lt;br /&gt;
* &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость;&lt;br /&gt;
* &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0, ~\delta &amp;gt; 0&amp;lt;/math&amp;gt; - коэффициенты, описывающие точность алгоритма.&lt;br /&gt;
Объем входных данных: &amp;lt;math&amp;gt; K*N &amp;lt;/math&amp;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; C*K &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
*Соотношение последовательной и параллельной сложности алгоритма: &amp;lt;math&amp;gt;C*C*K \over {\log_{2} {K} + \log_{2} C^4}&amp;lt;/math&amp;gt;. Соответственно при распараллеливании наибольший прирост в производительности мы получим при разбиении большого набора данных на большее число кластеров;&lt;br /&gt;
*Вычислительная мощность: &amp;lt;math&amp;gt;{{C^2*K} \over {C*K}} = C&amp;lt;/math&amp;gt;. Получается, что на чем большее количество кластеров мы разбиваем набор данных, тем менее затратным становится перемещение данных;&lt;br /&gt;
*Алгоритм не является устойчивым, как и другие подобные алгоритмы этого класса(например k-means). Очень многое зависит как от входных данных, так и от изначальных параметров приближения(заполнения матрицы принадлежности =&amp;gt; исходных центров кластеров);&lt;br /&gt;
*Не является детерминированным. Так же очень многое зависит как от входных данных, так и от изначальных параметров приближения(заполнения матрицы принадлежности =&amp;gt; исходных центров кластеров);&lt;br /&gt;
*Алгоритм не сбалансирован - доминирует операция умножения. Параллельные ветви алгоритма сбалансированы;&lt;br /&gt;
*Степень исхода вершины информационного графа - 2.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
Проведём исследование масштабируемости параллельной реализации разложения Холецкого согласно [[Scalability methodology|методике]]. Исследование проводилось на суперкомпьютере &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;
&lt;br /&gt;
Набор и границы значений изменяемых [[Глоссарий#Параметры запуска|параметров запуска]] реализации алгоритма: &lt;br /&gt;
&lt;br /&gt;
*	число процессоров [1 : 120];&lt;br /&gt;
*	размер входных данных  [1 : 15 000] векторов размерности 4.&lt;br /&gt;
При количестве кластеров 100.&lt;br /&gt;
&lt;br /&gt;
В результате проведённых экспериментов был получен следующий диапазон [[Глоссарий#Эффективность реализации|эффективности реализации]] алгоритма:&lt;br /&gt;
&lt;br /&gt;
*	минимальная эффективность реализации 0,63%;&lt;br /&gt;
*	максимальная эффективность реализации 2,56%.&lt;br /&gt;
&lt;br /&gt;
В параллельной реализации использовалась технология OpenMP. Компилятор GNU(gcc) с флагом -fopenmp. Версия компилятора: gcc version 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC).&lt;br /&gt;
&lt;br /&gt;
На следующих рисунках приведены графики [[Глоссарий#Производительность|производительности]] и  [[Глоссарий#Эффективность реализации|эффективности]] выбранной реализации в зависимости от изменяемых параметров запуска.&lt;br /&gt;
&lt;br /&gt;
[[file: FCM произв.jpg |thumb|center|800px|Рисунок 2 Изменение производительности.]]&lt;br /&gt;
&lt;br /&gt;
[[file: FCM эф.jpg |thumb|center|800px|Рисунок 3 Изменение эффективности.]]&lt;br /&gt;
&lt;br /&gt;
Оценки масштабируемости:&lt;br /&gt;
*	По числу процессов: 0.1245. &lt;br /&gt;
*	По размеру задачи: -0.0278. &lt;br /&gt;
*	По двум направлениям: 0,00009.&lt;br /&gt;
&lt;br /&gt;
[http://pastebin.com/LDPNY5Ua Параллельная реализация на языке С с использованием Open MP]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Можно найти следующие реализации алгоритма&lt;br /&gt;
* Для MATLAB http://www.mathworks.com/help/fuzzy/fcm.html &lt;br /&gt;
* В PostgreSQL http://num-meth.srcc.msu.ru/zhurnal/tom_2012/v13r207.html&lt;br /&gt;
Так же готовые реализации алгоритма и его описание можно найти на сайтах&lt;br /&gt;
* https://habrahabr.ru/post/208496/&lt;br /&gt;
* http://pythonhosted.org/scikit-fuzzy/auto_examples/plot_cmeans.html&lt;br /&gt;
* http://www.codeproject.com/Articles/91675/Computer-Vision-Applications-with-C-Fuzzy-C-means&lt;br /&gt;
* https://github.com/gyaikhom/fcm&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>ADovganich</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:FCM_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2.jpg&amp;diff=20148</id>
		<title>Файл:FCM произв.jpg</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:FCM_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2.jpg&amp;diff=20148"/>
		<updated>2016-12-05T21:57:42Z</updated>

		<summary type="html">&lt;p&gt;ADovganich: ADovganich загрузил новую версию Файл:FCM произв.jpg&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>ADovganich</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=18521</id>
		<title>Участник:ADovganich/Нечеткий алгоритм С средних</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=18521"/>
		<updated>2016-11-19T22:08:58Z</updated>

		<summary type="html">&lt;p&gt;ADovganich: /* Масштабируемость алгоритма и его реализации */&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(C*C*K*I)&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;K*N&amp;lt;/math&amp;gt;, [количество векторов * размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;C*K&amp;lt;/math&amp;gt;, [элементы матрицы принадлежности]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;3I&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;C*C*K&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Protsenko|Мария Проценко]] (1.5-1.8, 2.7), [[Участник:ADovganich|Андрей Довганич]] (1.1-1.4, 1.9, 1.10)&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Нечеткий алгоритм C-средних (fuzzy C-means) позволяет разбить имеющееся множество векторов (точек) мощностью &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; на заданное число нечетких множеств. Предназначен для кластеризации больших наборов данных. Основным достоинством алгоритма является нечеткость при определении объекта в кластер. Благодаря этому становится возможным определить объекты, которые находятся на границе, в кластеры. Из основного достоинства следует и главный недостаток - неопределенность с объектами, удаленными от центров всех кластеров. В остальном ему присущи стандартные проблемы подобного класса алгоритмов: вычислительная сложность, необходимость задания количества кластеров&amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм был разработан J.C. Dunn в 1973 г.&amp;lt;ref&amp;gt; Dunn, J. C. (1973-01-01). &amp;quot;A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters&amp;quot;. Journal of Cybernetics. 3 (3): 32–57. doi:10.1080/01969727308546046. ISSN 0022-0280.&amp;lt;/ref&amp;gt;, усовершенствован J.C. Bezdek в 1981 г.&amp;lt;ref&amp;gt; Bezdek, James C. (1981). Pattern Recognition with Fuzzy Objective Function Algorithms. ISBN 0-306-40671-3.&amp;lt;/ref&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;
# Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим матрицу &amp;lt;math&amp;gt; M = m_{ik} \in[0,1],\;  i = 1, ..., c, \; k = 1, ..., K &amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;m_{i,k}&amp;lt;/math&amp;gt; - вероятность принадлежности объекта &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; - количество векторов. При этом элементы матрицы удовлетворяют следующим условиям:&lt;br /&gt;
&lt;br /&gt;
* сумма элементов в каждом столбце равна &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* сумма всех элементов матрицы равно &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Назовем &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; матрицей принадлежности.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; - центры кластеров. Тогда рассмотрим функцию &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
J(M, c_{1}, c_{2},...c_{c}) = \sum_{i = 1}^{c}{J_{i}} = \sum_{i = 1}^{c}\sum_{k = 1}^{K}{m_{ik}^q}d_{ik}^2 ~(1)&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt; d_{ik} = \left\Vert{u_{k}-c_{i}}\right\| &amp;lt;/math&amp;gt; - Евклидово расстояние между центром кластера и объектом, &amp;lt;math&amp;gt; 1 \le q \le \infty &amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость. Будем минимизировать значение функции &amp;lt;math&amp;gt; J &amp;lt;/math&amp;gt;. Для этого вычислим центры кластеров по формуле &amp;lt;math&amp;gt; ~(2) &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c_{i} = {{\sum_{k = 1}^{K}{m_{ik}^q} * u_{k}} \over {\sum_{k = 1}^{K}{m_{ik}^q}}}~(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;m_{ik}&amp;lt;/math&amp;gt; — коэффициент принадлежности &amp;lt;math&amp;gt;u_{k}&amp;lt;/math&amp;gt; вектора к кластеру &amp;lt;math&amp;gt;c_{i}&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
и новые значения матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; по формуле &amp;lt;math&amp;gt; ~(3) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;m_{ik} = {1 \over \sum_{j = 1}^{c}{({{d_{ik}} \over {d_{jk}}})}^{2 \over q-1}} ~(3)&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; ~(2) &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; ~(3) &amp;lt;/math&amp;gt;являются необходимым условиями достижения минимума функцией &amp;lt;math&amp;gt; J &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; случайными значениями от 0 до 1;&lt;br /&gt;
# Вычислить центры кластеров &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; используя формулу &amp;lt;math&amp;gt;~(2)&amp;lt;/math&amp;gt;;&lt;br /&gt;
# Вычислить значение решающей функции по формуле &amp;lt;math&amp;gt;~(1)&amp;lt;/math&amp;gt;. Если значение &amp;lt;math&amp;gt; J &amp;lt; \varepsilon,~\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt; |J_{i} - J_{i-1}| &amp;lt; \delta,~\delta &amp;gt; 0 &amp;lt;/math&amp;gt;, то остановить вычисления;&lt;br /&gt;
# Иначе вычислить новые значения матрицы М по формуле &amp;lt;math&amp;gt;~(3)&amp;lt;/math&amp;gt;;&lt;br /&gt;
# Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительным ядром алгоритма являются формулы: &amp;lt;math&amp;gt; (1) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (2) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (3) &amp;lt;/math&amp;gt;. В них производится вычисление новых центров кластеров, значения решающей функции и пересчет элементов матрицы принадлежности.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Макроструктура алгоритма состоит из следующих шагов:&lt;br /&gt;
&lt;br /&gt;
# Инициализация матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; случайными значениями от 0 до 1;&lt;br /&gt;
# Вычисление центров кластеров; &lt;br /&gt;
# Вычисление значения решающей функции(если оно удовлетворяет условиям останова - завершение вычислений);&lt;br /&gt;
# Вычисление новых элементов матрицы принадлежности;&lt;br /&gt;
# Переход к шагу 2;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации алгоритма на языке С++. Сначала вычислим центры кластеров, потом вычислим решающую функцию, с ее помощью определим необходимость продолжать алгоритм, и при необходимости вычислим новые значения матрицы M.&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    float ** m;&lt;br /&gt;
    int *c;&lt;br /&gt;
    int number_clusters, number_items;&lt;br /&gt;
    m = gen_random_clusters();//заполним матрицу m случайными значениями от 0 до 1&lt;br /&gt;
    &lt;br /&gt;
    while (true)&lt;br /&gt;
    {&lt;br /&gt;
      //вычисление центров кластеров&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
        {&lt;br /&gt;
            numerator==denumerator=0;&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
            {&lt;br /&gt;
                numerator+=pow(m[i, k], q)*u[k];//u[k]-вектор&lt;br /&gt;
                denumerator+=pow(m[i, k], q);&lt;br /&gt;
            }&lt;br /&gt;
        c[i]= numerator / denumerator;//центры кластеров&lt;br /&gt;
        }&lt;br /&gt;
    &lt;br /&gt;
        j=0;//вычисление решающей функции&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
                j+=pow(m[i, k], q)*pow(dist(c[i], x[k],2);//dist-вычисляет расстояние между заданными векторами&lt;br /&gt;
    &lt;br /&gt;
       if ((abs(j-last_j)&amp;lt;delta) || (j&amp;lt;eps)) break;//проверка на необходимость завернешения алгоритма&lt;br /&gt;
       last_j=j;&lt;br /&gt;
     //обновление матрицы m&lt;br /&gt;
       for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
          for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
             {&lt;br /&gt;
               m[i,k]=0&lt;br /&gt;
              for(int j=0; j&amp;lt;number_clusters; j++)&lt;br /&gt;
                  m[i,k]+=pow(dist(c[i], x[k])/dist(c[j], x[k]),2/(q-1));&lt;br /&gt;
              m[i,k]=1/m[i,k];&lt;br /&gt;
              }&lt;br /&gt;
                                       &lt;br /&gt;
    }&lt;br /&gt;
    &amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Каждая итерация включает в себя&lt;br /&gt;
* Вычисление центров кластеров &amp;lt;math&amp;gt;O(C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
* Вычисление решающей функции &amp;lt;math&amp;gt;O(C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
* Обновлене матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;O(C*C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
Общая сложность каждой итерации &amp;lt;math&amp;gt;O(C*C*K)&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;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; параллельных операций, каждая их которых в свою очередь состоит из &amp;lt;math&amp;gt;K&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;C*K&amp;lt;/math&amp;gt; параллельных операций.&lt;br /&gt;
Результатом его работы является значение решающей функции &amp;lt;math&amp;gt;J&amp;lt;/math&amp;gt;. Её значение определяет необходимость завершения алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Третий ярус&#039;&#039;&#039; включает &amp;lt;math&amp;gt;C*K&amp;lt;/math&amp;gt; параллельных операций, каждая из которых состоит из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; параллельных операций, и одной, которая выполняется с использованием результата предыдущих.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Суперпрак.png|1200px|thumb|center|Информационный граф алгоритма. Салатовым цветом обозначены вершины графа-операции. Дугами обозначена передача информации, передаваемые данные надписаны сверху.]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
На каждом шаге алгоритма необходимо вычислять сумму элементов массивов. Сложность ее вычисления на первом шаге (вычисление центров кластеров) при параллельной реализации составляет &amp;lt;math&amp;gt;O(\log_{2} C)&amp;lt;/math&amp;gt;. Для каждого элемента из набора входных данных(&amp;lt;math&amp;gt; K &amp;lt;/math&amp;gt;), но здесь возможен независимый расчет(координатный параллелизм). На втором шаге(вычисление решающей функции) сложность будет &amp;lt;math&amp;gt;O(\log_{2} {C*K})&amp;lt;/math&amp;gt;, потому что здесь необходимо сложение всех элементов. На третьем шаге имеем сложность &amp;lt;math&amp;gt;O(\log_{2} C^2)&amp;lt;/math&amp;gt;. Итого суммарная сложность итерации: &amp;lt;math&amp;gt;O(\log_{2} {C*K} + \log_{2} C^3)&amp;lt;/math&amp;gt;. Воспользовавшись свойствами логарифма произведения получаем: &amp;lt;math&amp;gt;O(\log_{2} {K} + \log_{2} C^4)&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Скошенного параллелизма в алгоритме нет.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Входные данные:&lt;br /&gt;
* &amp;lt;math&amp;gt;u_{k} ~k = 1, ..., K&amp;lt;/math&amp;gt; - набор входных векторов размерности &amp;lt;math&amp;gt; N &amp;lt;/math&amp;gt;;&lt;br /&gt;
* &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; - количество кластеров;&lt;br /&gt;
* &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость;&lt;br /&gt;
* &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0, ~\delta &amp;gt; 0&amp;lt;/math&amp;gt; - коэффициенты, описывающие точность алгоритма.&lt;br /&gt;
Объем входных данных: &amp;lt;math&amp;gt; K*N &amp;lt;/math&amp;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; C*K &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
*Соотношение последовательной и параллельной сложности алгоритма: &amp;lt;math&amp;gt;C*C*K \over {\log_{2} {K} + \log_{2} C^4}&amp;lt;/math&amp;gt;. Соответственно при распараллеливании наибольший прирост в производительности мы получим при разбиении большого набора данных на большее число кластеров;&lt;br /&gt;
*Вычислительная мощность: &amp;lt;math&amp;gt;{{C^2*K} \over {C*K}} = C&amp;lt;/math&amp;gt;. Получается, что на чем большее количество кластеров мы разбиваем набор данных, тем менее затратным становится перемещение данных;&lt;br /&gt;
*Алгоритм не является устойчивым, как и другие подобные алгоритмы этого класса(например k-means). Очень многое зависит как от входных данных, так и от изначальных параметров приближения(заполнения матрицы принадлежности =&amp;gt; исходных центров кластеров);&lt;br /&gt;
*Не является детерминированным. Так же очень многое зависит как от входных данных, так и от изначальных параметров приближения(заполнения матрицы принадлежности =&amp;gt; исходных центров кластеров);&lt;br /&gt;
*Алгоритм не сбалансирован - доминирует операция умножения. Параллельные ветви алгоритма сбалансированы;&lt;br /&gt;
*Степень исхода вершины информационного графа - 2.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
Проведём исследование масштабируемости параллельной реализации разложения Холецкого согласно [[Scalability methodology|методике]]. Исследование проводилось на суперкомпьютере &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;
&lt;br /&gt;
Набор и границы значений изменяемых [[Глоссарий#Параметры запуска|параметров запуска]] реализации алгоритма: &lt;br /&gt;
&lt;br /&gt;
*	число процессоров [1 : 120];&lt;br /&gt;
*	размер входных данных  [1 : 15 000] векторов размерности 4.&lt;br /&gt;
При количестве кластеров 100.&lt;br /&gt;
&lt;br /&gt;
В результате проведённых экспериментов был получен следующий диапазон [[Глоссарий#Эффективность реализации|эффективности реализации]] алгоритма:&lt;br /&gt;
&lt;br /&gt;
*	минимальная эффективность реализации 0,63%;&lt;br /&gt;
*	максимальная эффективность реализации 2,56%.&lt;br /&gt;
&lt;br /&gt;
В параллельной реализации использовалась технология OpenMP. Компилятор GNU(gcc) с флагом -fopenmp. Версия компилятора: gcc version 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC).&lt;br /&gt;
&lt;br /&gt;
На следующих рисунках приведены графики [[Глоссарий#Производительность|производительности]] и  [[Глоссарий#Эффективность реализации|эффективности]] выбранной реализации в зависимости от изменяемых параметров запуска.&lt;br /&gt;
&lt;br /&gt;
[[file: FCM произв.jpg |thumb|center|800px|Изменение производительности.]]&lt;br /&gt;
&lt;br /&gt;
[[file: FCM эф.jpg |thumb|center|800px|Изменение эффективности.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[http://pastebin.com/LDPNY5Ua Параллельная реализация на языке С с использованием Open MP]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Можно найти следующие реализации алгоритма&lt;br /&gt;
* Для MATLAB http://www.mathworks.com/help/fuzzy/fcm.html &lt;br /&gt;
* В PostgreSQL http://num-meth.srcc.msu.ru/zhurnal/tom_2012/v13r207.html&lt;br /&gt;
Так же готовые реализации алгоритма и его описание можно найти на сайтах&lt;br /&gt;
* https://habrahabr.ru/post/208496/&lt;br /&gt;
* http://pythonhosted.org/scikit-fuzzy/auto_examples/plot_cmeans.html&lt;br /&gt;
* http://www.codeproject.com/Articles/91675/Computer-Vision-Applications-with-C-Fuzzy-C-means&lt;br /&gt;
* https://github.com/gyaikhom/fcm&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>ADovganich</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=14548</id>
		<title>Участник:ADovganich/Нечеткий алгоритм С средних</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=14548"/>
		<updated>2016-10-28T15:28:59Z</updated>

		<summary type="html">&lt;p&gt;ADovganich: /* Входные и выходные данные алгоритма */&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(C*C*K*I)&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;K*N&amp;lt;/math&amp;gt;, [количество векторов * размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;C*K&amp;lt;/math&amp;gt;, [элементы матрицы принадлежности]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;3I&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;C*C*K&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Protsenko|Мария Проценко]] (1.5-1.8, 2.7), [[Участник:ADovganich|Андрей Довганич]] (1.1-1.4, 1.9, 1.10)&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Нечеткий алгоритм C-средних (fuzzy C-means) позволяет разбить имеющееся множество векторов (точек) мощностью &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; на заданное число нечетких множеств. Предназначен для кластеризации больших наборов данных. Основным достоинством алгоритма является нечеткость при определении объекта в кластер. Благодаря этому становится возможным определить объекты, которые находятся на границе, в кластеры. Из основного достоинства следует и главный недостаток - неопределенность с объектами, удаленными от центров всех кластеров. В остальном ему присущи стандартные проблемы подобного класса алгоритмов: вычислительная сложность, необходимость задания количества кластеров&amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм был разработан J.C. Dunn в 1973 г.&amp;lt;ref&amp;gt; Dunn, J. C. (1973-01-01). &amp;quot;A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters&amp;quot;. Journal of Cybernetics. 3 (3): 32–57. doi:10.1080/01969727308546046. ISSN 0022-0280.&amp;lt;/ref&amp;gt;, усовершенствован J.C. Bezdek в 1981 г.&amp;lt;ref&amp;gt; Bezdek, James C. (1981). Pattern Recognition with Fuzzy Objective Function Algorithms. ISBN 0-306-40671-3.&amp;lt;/ref&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;
# Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим матрицу &amp;lt;math&amp;gt; M = m_{ik} \in[0,1],\;  i = 1, ..., c, \; k = 1, ..., K &amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;m_{i,k}&amp;lt;/math&amp;gt; - вероятность принадлежности объекта &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; - количество векторов. При этом элементы матрицы удовлетворяют следующим условиям:&lt;br /&gt;
&lt;br /&gt;
* сумма элементов в каждом столбце равна &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* сумма всех элементов матрицы равно &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Назовем &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; матрицей принадлежности.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; - центры кластеров. Тогда рассмотрим функцию &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
J(M, c_{1}, c_{2},...c_{c}) = \sum_{i = 1}^{c}{J_{i}} = \sum_{i = 1}^{c}\sum_{k = 1}^{K}{m_{ik}^q}d_{ik}^2 ~(1)&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt; d_{ik} = \left\Vert{u_{k}-c_{i}}\right\| &amp;lt;/math&amp;gt; - Евклидово расстояние между центром кластера и объектом, &amp;lt;math&amp;gt; 1 \le q \le \infty &amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость. Будем минимизировать значение функции &amp;lt;math&amp;gt; J &amp;lt;/math&amp;gt;. Для этого вычислим центры кластеров по формуле &amp;lt;math&amp;gt; ~(2) &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c_{i} = {{\sum_{k = 1}^{K}{m_{ik}^q} * u_{k}} \over {\sum_{k = 1}^{K}{m_{ik}^q}}}~(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;m_{ik}&amp;lt;/math&amp;gt; — коэффициент принадлежности &amp;lt;math&amp;gt;u_{k}&amp;lt;/math&amp;gt; вектора к кластеру &amp;lt;math&amp;gt;c_{i}&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
и новые значения матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; по формуле &amp;lt;math&amp;gt; ~(3) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;m_{ik} = {1 \over \sum_{j = 1}^{c}{({{d_{ik}} \over {d_{jk}}})}^{2 \over q-1}} ~(3)&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; ~(2) &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; ~(3) &amp;lt;/math&amp;gt;являются необходимым условиями достижения минимума функцией &amp;lt;math&amp;gt; J &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; случайными значениями от 0 до 1;&lt;br /&gt;
# Вычислить центры кластеров &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; используя формулу &amp;lt;math&amp;gt;~(2)&amp;lt;/math&amp;gt;;&lt;br /&gt;
# Вычислить значение решающей функции по формуле &amp;lt;math&amp;gt;~(1)&amp;lt;/math&amp;gt;. Если значение &amp;lt;math&amp;gt; J &amp;lt; \varepsilon,~\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt; |J_{i} - J_{i-1}| &amp;lt; \delta,~\delta &amp;gt; 0 &amp;lt;/math&amp;gt;, то остановить вычисления;&lt;br /&gt;
# Иначе вычислить новые значения матрицы М по формуле &amp;lt;math&amp;gt;~(3)&amp;lt;/math&amp;gt;;&lt;br /&gt;
# Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительным ядром алгоритма являются формулы: &amp;lt;math&amp;gt; (1) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (2) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (3) &amp;lt;/math&amp;gt;. В них производится вычисление новых центров кластеров, значения решающей функции и пересчет элементов матрицы принадлежности.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Макроструктура алгоритма состоит из следующих шагов:&lt;br /&gt;
&lt;br /&gt;
# Инициализация матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; случайными значениями от 0 до 1;&lt;br /&gt;
# Вычисление центров кластеров; &lt;br /&gt;
# Вычисление значения решающей функции(если оно удовлетворяет условиям останова - завершение вычислений);&lt;br /&gt;
# Вычисление новых элементов матрицы принадлежности;&lt;br /&gt;
# Переход к шагу 2;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации алгоритма на языке С++&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    float ** m;&lt;br /&gt;
    int *c;&lt;br /&gt;
    int number_clusters, number_items;&lt;br /&gt;
    m = gen_random_clusters();//заполним матрицу m случайными значениями от 0 до 1&lt;br /&gt;
    &lt;br /&gt;
    while (true)&lt;br /&gt;
    {&lt;br /&gt;
      //вычисление центров кластеров&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
        {&lt;br /&gt;
            numerator==denumerator=0;&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
            {&lt;br /&gt;
                numerator+=pow(m[i, k], q)*u[k];//u[k]-вектор&lt;br /&gt;
                denumerator+=pow(m[i, k], q);&lt;br /&gt;
            }&lt;br /&gt;
        c[i]= numerator / denumerator;//центры кластеров&lt;br /&gt;
        }&lt;br /&gt;
    &lt;br /&gt;
        j=0;//вычисление решающей функции&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
                j+=pow(m[i, k], q)*pow(dist(c[i], x[k],2);//dist-вычисляет расстояние между заданными векторами&lt;br /&gt;
    &lt;br /&gt;
       if ((abs(j-last_j)&amp;lt;delta) || (j&amp;lt;eps)) break;//проверка на необходимость завернешения алгоритма&lt;br /&gt;
       last_j=j;&lt;br /&gt;
     //обновление матрицы m&lt;br /&gt;
       for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
          for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
             {&lt;br /&gt;
               m[i,k]=0&lt;br /&gt;
              for(int j=0; j&amp;lt;number_clusters; j++)&lt;br /&gt;
                  m[i,k]+=pow(dist(c[i], x[k])/dist(c[j], x[k]),2/(q-1));&lt;br /&gt;
              m[i,k]=1/m[i,k];&lt;br /&gt;
              }&lt;br /&gt;
                                       &lt;br /&gt;
    }&lt;br /&gt;
    &amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Каждая итерация включает в себя&lt;br /&gt;
* Вычисление центров кластеров &amp;lt;math&amp;gt;O(C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
* Вычисление решающей функции &amp;lt;math&amp;gt;O(C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
* Обновлене матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;O(C*C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
Общая сложность каждой итерации &amp;lt;math&amp;gt;O(C*C*K)&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;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; параллельных операций, каждая их которых в свою очередь состоит из &amp;lt;math&amp;gt;K&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;C*K&amp;lt;/math&amp;gt; параллельных операций.&lt;br /&gt;
Результатом его работы является значение решающей функции &amp;lt;math&amp;gt;J&amp;lt;/math&amp;gt;. Её значение определяет необходимость завершения алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Третий ярус&#039;&#039;&#039; включает &amp;lt;math&amp;gt;C*K&amp;lt;/math&amp;gt; параллельных операций, каждая из которых состоит из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; параллельных операций, и одной, которая выполняется с использованием результата предыдущих.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Снимок экрана 2016-10-15 в 23.10.05.png|582 px|thumb|center|Информационный граф]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
На каждом шаге алгоритма необходимо вычислять сумму элементов массивов. Сложность ее вычисления на первом шаге (вычисление центров кластеров) при параллельной реализации составляет &amp;lt;math&amp;gt;O(\log_{2} C)&amp;lt;/math&amp;gt;. Для каждого элемента из набора входных данных(&amp;lt;math&amp;gt; K &amp;lt;/math&amp;gt;), но здесь возможен независимый расчет(координатный параллелизм). На втором шаге(вычисление решающей функции) сложность будет &amp;lt;math&amp;gt;O(\log_{2} {C*K})&amp;lt;/math&amp;gt;, потому что здесь необходимо сложение всех элементов. На третьем шаге имеем сложность &amp;lt;math&amp;gt;O(\log_{2} C^2)&amp;lt;/math&amp;gt;. Итого суммарная сложность итерации: &amp;lt;math&amp;gt;O(\log_{2} {C*K} + \log_{2} C^3)&amp;lt;/math&amp;gt;. Воспользовавшись свойствами логарифма произведения получаем: &amp;lt;math&amp;gt;O(\log_{2} {K} + \log_{2} C^4)&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Скошенного параллелизма в алгоритме нет.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Входные данные:&lt;br /&gt;
* &amp;lt;math&amp;gt;u_{k} ~k = 1, ..., K&amp;lt;/math&amp;gt; - набор входных векторов размерности &amp;lt;math&amp;gt; N &amp;lt;/math&amp;gt;;&lt;br /&gt;
* &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; - количество кластеров;&lt;br /&gt;
* &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость;&lt;br /&gt;
* &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0, ~\delta &amp;gt; 0&amp;lt;/math&amp;gt; - коэффициенты, описывающие точность алгоритма.&lt;br /&gt;
Объем входных данных: &amp;lt;math&amp;gt; K*N &amp;lt;/math&amp;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; C*K &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
*Соотношение последовательной и параллельной сложности алгоритма: &amp;lt;math&amp;gt;C*C*K \over {\log_{2} {K} + \log_{2} C^4}&amp;lt;/math&amp;gt;. Соответственно при распараллеливании наибольший прирост в производительности мы получим при разбиении большого набора данных на большее число кластеров;&lt;br /&gt;
*Вычислительная мощность: &amp;lt;math&amp;gt;{{C^2*K} \over {C*K}} = C&amp;lt;/math&amp;gt;. Получается, что на чем большее количество кластеров мы разбиваем набор данных, тем менее затратным становится перемещение данных;&lt;br /&gt;
*Алгоритм не является устойчивым, как и другие подобные алгоритмы этого класса(например k-means). Очень многое зависит как от входных данных, так и от изначальных параметров приближения(заполнения матрицы принадлежности =&amp;gt; исходных центров кластеров);&lt;br /&gt;
*Не является детерминированным. Так же очень многое зависит как от входных данных, так и от изначальных параметров приближения(заполнения матрицы принадлежности =&amp;gt; исходных центров кластеров);&lt;br /&gt;
*Алгоритм не сбалансирован - доминирует операция умножения. Параллельные ветви алгоритма сбалансированы;&lt;br /&gt;
*Степень исхода вершины информационного графа - 2.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Можно найти следующие реализации алгоритма&lt;br /&gt;
* Для MATLAB http://www.mathworks.com/help/fuzzy/fcm.html &lt;br /&gt;
* В PostgreSQL http://num-meth.srcc.msu.ru/zhurnal/tom_2012/v13r207.html&lt;br /&gt;
Так же готовые реализации алгоритма и его описание можно найти на сайтах&lt;br /&gt;
* https://habrahabr.ru/post/208496/&lt;br /&gt;
* http://pythonhosted.org/scikit-fuzzy/auto_examples/plot_cmeans.html&lt;br /&gt;
* http://www.codeproject.com/Articles/91675/Computer-Vision-Applications-with-C-Fuzzy-C-means&lt;br /&gt;
* https://github.com/gyaikhom/fcm&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>ADovganich</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=14547</id>
		<title>Участник:ADovganich/Нечеткий алгоритм С средних</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=14547"/>
		<updated>2016-10-28T15:28:35Z</updated>

		<summary type="html">&lt;p&gt;ADovganich: &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(C*C*K*I)&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;K*N&amp;lt;/math&amp;gt;, [количество векторов * размерность]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;C*K&amp;lt;/math&amp;gt;, [элементы матрицы принадлежности]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;3I&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;C*C*K&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Protsenko|Мария Проценко]] (1.5-1.8, 2.7), [[Участник:ADovganich|Андрей Довганич]] (1.1-1.4, 1.9, 1.10)&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Нечеткий алгоритм C-средних (fuzzy C-means) позволяет разбить имеющееся множество векторов (точек) мощностью &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; на заданное число нечетких множеств. Предназначен для кластеризации больших наборов данных. Основным достоинством алгоритма является нечеткость при определении объекта в кластер. Благодаря этому становится возможным определить объекты, которые находятся на границе, в кластеры. Из основного достоинства следует и главный недостаток - неопределенность с объектами, удаленными от центров всех кластеров. В остальном ему присущи стандартные проблемы подобного класса алгоритмов: вычислительная сложность, необходимость задания количества кластеров&amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм был разработан J.C. Dunn в 1973 г.&amp;lt;ref&amp;gt; Dunn, J. C. (1973-01-01). &amp;quot;A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters&amp;quot;. Journal of Cybernetics. 3 (3): 32–57. doi:10.1080/01969727308546046. ISSN 0022-0280.&amp;lt;/ref&amp;gt;, усовершенствован J.C. Bezdek в 1981 г.&amp;lt;ref&amp;gt; Bezdek, James C. (1981). Pattern Recognition with Fuzzy Objective Function Algorithms. ISBN 0-306-40671-3.&amp;lt;/ref&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;
# Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим матрицу &amp;lt;math&amp;gt; M = m_{ik} \in[0,1],\;  i = 1, ..., c, \; k = 1, ..., K &amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;m_{i,k}&amp;lt;/math&amp;gt; - вероятность принадлежности объекта &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; - количество векторов. При этом элементы матрицы удовлетворяют следующим условиям:&lt;br /&gt;
&lt;br /&gt;
* сумма элементов в каждом столбце равна &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* сумма всех элементов матрицы равно &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Назовем &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; матрицей принадлежности.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; - центры кластеров. Тогда рассмотрим функцию &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
J(M, c_{1}, c_{2},...c_{c}) = \sum_{i = 1}^{c}{J_{i}} = \sum_{i = 1}^{c}\sum_{k = 1}^{K}{m_{ik}^q}d_{ik}^2 ~(1)&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt; d_{ik} = \left\Vert{u_{k}-c_{i}}\right\| &amp;lt;/math&amp;gt; - Евклидово расстояние между центром кластера и объектом, &amp;lt;math&amp;gt; 1 \le q \le \infty &amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость. Будем минимизировать значение функции &amp;lt;math&amp;gt; J &amp;lt;/math&amp;gt;. Для этого вычислим центры кластеров по формуле &amp;lt;math&amp;gt; ~(2) &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c_{i} = {{\sum_{k = 1}^{K}{m_{ik}^q} * u_{k}} \over {\sum_{k = 1}^{K}{m_{ik}^q}}}~(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;m_{ik}&amp;lt;/math&amp;gt; — коэффициент принадлежности &amp;lt;math&amp;gt;u_{k}&amp;lt;/math&amp;gt; вектора к кластеру &amp;lt;math&amp;gt;c_{i}&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
и новые значения матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; по формуле &amp;lt;math&amp;gt; ~(3) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;m_{ik} = {1 \over \sum_{j = 1}^{c}{({{d_{ik}} \over {d_{jk}}})}^{2 \over q-1}} ~(3)&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; ~(2) &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; ~(3) &amp;lt;/math&amp;gt;являются необходимым условиями достижения минимума функцией &amp;lt;math&amp;gt; J &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; случайными значениями от 0 до 1;&lt;br /&gt;
# Вычислить центры кластеров &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; используя формулу &amp;lt;math&amp;gt;~(2)&amp;lt;/math&amp;gt;;&lt;br /&gt;
# Вычислить значение решающей функции по формуле &amp;lt;math&amp;gt;~(1)&amp;lt;/math&amp;gt;. Если значение &amp;lt;math&amp;gt; J &amp;lt; \varepsilon,~\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt; |J_{i} - J_{i-1}| &amp;lt; \delta,~\delta &amp;gt; 0 &amp;lt;/math&amp;gt;, то остановить вычисления;&lt;br /&gt;
# Иначе вычислить новые значения матрицы М по формуле &amp;lt;math&amp;gt;~(3)&amp;lt;/math&amp;gt;;&lt;br /&gt;
# Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительным ядром алгоритма являются формулы: &amp;lt;math&amp;gt; (1) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (2) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (3) &amp;lt;/math&amp;gt;. В них производится вычисление новых центров кластеров, значения решающей функции и пересчет элементов матрицы принадлежности.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Макроструктура алгоритма состоит из следующих шагов:&lt;br /&gt;
&lt;br /&gt;
# Инициализация матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; случайными значениями от 0 до 1;&lt;br /&gt;
# Вычисление центров кластеров; &lt;br /&gt;
# Вычисление значения решающей функции(если оно удовлетворяет условиям останова - завершение вычислений);&lt;br /&gt;
# Вычисление новых элементов матрицы принадлежности;&lt;br /&gt;
# Переход к шагу 2;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации алгоритма на языке С++&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    float ** m;&lt;br /&gt;
    int *c;&lt;br /&gt;
    int number_clusters, number_items;&lt;br /&gt;
    m = gen_random_clusters();//заполним матрицу m случайными значениями от 0 до 1&lt;br /&gt;
    &lt;br /&gt;
    while (true)&lt;br /&gt;
    {&lt;br /&gt;
      //вычисление центров кластеров&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
        {&lt;br /&gt;
            numerator==denumerator=0;&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
            {&lt;br /&gt;
                numerator+=pow(m[i, k], q)*u[k];//u[k]-вектор&lt;br /&gt;
                denumerator+=pow(m[i, k], q);&lt;br /&gt;
            }&lt;br /&gt;
        c[i]= numerator / denumerator;//центры кластеров&lt;br /&gt;
        }&lt;br /&gt;
    &lt;br /&gt;
        j=0;//вычисление решающей функции&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
                j+=pow(m[i, k], q)*pow(dist(c[i], x[k],2);//dist-вычисляет расстояние между заданными векторами&lt;br /&gt;
    &lt;br /&gt;
       if ((abs(j-last_j)&amp;lt;delta) || (j&amp;lt;eps)) break;//проверка на необходимость завернешения алгоритма&lt;br /&gt;
       last_j=j;&lt;br /&gt;
     //обновление матрицы m&lt;br /&gt;
       for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
          for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
             {&lt;br /&gt;
               m[i,k]=0&lt;br /&gt;
              for(int j=0; j&amp;lt;number_clusters; j++)&lt;br /&gt;
                  m[i,k]+=pow(dist(c[i], x[k])/dist(c[j], x[k]),2/(q-1));&lt;br /&gt;
              m[i,k]=1/m[i,k];&lt;br /&gt;
              }&lt;br /&gt;
                                       &lt;br /&gt;
    }&lt;br /&gt;
    &amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Каждая итерация включает в себя&lt;br /&gt;
* Вычисление центров кластеров &amp;lt;math&amp;gt;O(C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
* Вычисление решающей функции &amp;lt;math&amp;gt;O(C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
* Обновлене матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;O(C*C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
Общая сложность каждой итерации &amp;lt;math&amp;gt;O(C*C*K)&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;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; параллельных операций, каждая их которых в свою очередь состоит из &amp;lt;math&amp;gt;K&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;C*K&amp;lt;/math&amp;gt; параллельных операций.&lt;br /&gt;
Результатом его работы является значение решающей функции &amp;lt;math&amp;gt;J&amp;lt;/math&amp;gt;. Её значение определяет необходимость завершения алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Третий ярус&#039;&#039;&#039; включает &amp;lt;math&amp;gt;C*K&amp;lt;/math&amp;gt; параллельных операций, каждая из которых состоит из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; параллельных операций, и одной, которая выполняется с использованием результата предыдущих.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Снимок экрана 2016-10-15 в 23.10.05.png|582 px|thumb|center|Информационный граф]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
На каждом шаге алгоритма необходимо вычислять сумму элементов массивов. Сложность ее вычисления на первом шаге (вычисление центров кластеров) при параллельной реализации составляет &amp;lt;math&amp;gt;O(\log_{2} C)&amp;lt;/math&amp;gt;. Для каждого элемента из набора входных данных(&amp;lt;math&amp;gt; K &amp;lt;/math&amp;gt;), но здесь возможен независимый расчет(координатный параллелизм). На втором шаге(вычисление решающей функции) сложность будет &amp;lt;math&amp;gt;O(\log_{2} {C*K})&amp;lt;/math&amp;gt;, потому что здесь необходимо сложение всех элементов. На третьем шаге имеем сложность &amp;lt;math&amp;gt;O(\log_{2} C^2)&amp;lt;/math&amp;gt;. Итого суммарная сложность итерации: &amp;lt;math&amp;gt;O(\log_{2} {C*K} + \log_{2} C^3)&amp;lt;/math&amp;gt;. Воспользовавшись свойствами логарифма произведения получаем: &amp;lt;math&amp;gt;O(\log_{2} {K} + \log_{2} C^4)&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Скошенного параллелизма в алгоритме нет.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Входные данные:&lt;br /&gt;
* &amp;lt;math&amp;gt;u_{k} ~k = 1, ..., K&amp;lt;/math&amp;gt; - набор входных векторов размерности &amp;lt;math&amp;gt; N &amp;lt;/math&amp;gt;;&lt;br /&gt;
* &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; - количество кластеров;&lt;br /&gt;
* &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость;&lt;br /&gt;
* &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0, ~\delta &amp;gt; 0&amp;lt;/math&amp;gt; - коэффициенты, описывающие точность алгоритма.&lt;br /&gt;
Объем входных данных: &amp;lt;math&amp;gt; K*N &amp;lt;/math&amp;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; C*K &amp;lt;/math&amp;gt; [элементы матрицы принадлежности]&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
*Соотношение последовательной и параллельной сложности алгоритма: &amp;lt;math&amp;gt;C*C*K \over {\log_{2} {K} + \log_{2} C^4}&amp;lt;/math&amp;gt;. Соответственно при распараллеливании наибольший прирост в производительности мы получим при разбиении большого набора данных на большее число кластеров;&lt;br /&gt;
*Вычислительная мощность: &amp;lt;math&amp;gt;{{C^2*K} \over {C*K}} = C&amp;lt;/math&amp;gt;. Получается, что на чем большее количество кластеров мы разбиваем набор данных, тем менее затратным становится перемещение данных;&lt;br /&gt;
*Алгоритм не является устойчивым, как и другие подобные алгоритмы этого класса(например k-means). Очень многое зависит как от входных данных, так и от изначальных параметров приближения(заполнения матрицы принадлежности =&amp;gt; исходных центров кластеров);&lt;br /&gt;
*Не является детерминированным. Так же очень многое зависит как от входных данных, так и от изначальных параметров приближения(заполнения матрицы принадлежности =&amp;gt; исходных центров кластеров);&lt;br /&gt;
*Алгоритм не сбалансирован - доминирует операция умножения. Параллельные ветви алгоритма сбалансированы;&lt;br /&gt;
*Степень исхода вершины информационного графа - 2.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Можно найти следующие реализации алгоритма&lt;br /&gt;
* Для MATLAB http://www.mathworks.com/help/fuzzy/fcm.html &lt;br /&gt;
* В PostgreSQL http://num-meth.srcc.msu.ru/zhurnal/tom_2012/v13r207.html&lt;br /&gt;
Так же готовые реализации алгоритма и его описание можно найти на сайтах&lt;br /&gt;
* https://habrahabr.ru/post/208496/&lt;br /&gt;
* http://pythonhosted.org/scikit-fuzzy/auto_examples/plot_cmeans.html&lt;br /&gt;
* http://www.codeproject.com/Articles/91675/Computer-Vision-Applications-with-C-Fuzzy-C-means&lt;br /&gt;
* https://github.com/gyaikhom/fcm&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>ADovganich</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=14546</id>
		<title>Участник:ADovganich/Нечеткий алгоритм С средних</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=14546"/>
		<updated>2016-10-28T15:25:41Z</updated>

		<summary type="html">&lt;p&gt;ADovganich: /* Входные и выходные данные алгоритма */&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(C*C*K*I)&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;K&amp;lt;/math&amp;gt;, [векторов]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;C*K&amp;lt;/math&amp;gt;, [элементы матрицы принадлежности]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;3I&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;C*C*K&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Protsenko|Мария Проценко]] (1.5-1.8, 2.7), [[Участник:ADovganich|Андрей Довганич]] (1.1-1.4, 1.9, 1.10)&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Нечеткий алгоритм C-средних (fuzzy C-means) позволяет разбить имеющееся множество векторов (точек) мощностью &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; на заданное число нечетких множеств. Предназначен для кластеризации больших наборов данных. Основным достоинством алгоритма является нечеткость при определении объекта в кластер. Благодаря этому становится возможным определить объекты, которые находятся на границе, в кластеры. Из основного достоинства следует и главный недостаток - неопределенность с объектами, удаленными от центров всех кластеров. В остальном ему присущи стандартные проблемы подобного класса алгоритмов: вычислительная сложность, необходимость задания количества кластеров&amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм был разработан J.C. Dunn в 1973 г.&amp;lt;ref&amp;gt; Dunn, J. C. (1973-01-01). &amp;quot;A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters&amp;quot;. Journal of Cybernetics. 3 (3): 32–57. doi:10.1080/01969727308546046. ISSN 0022-0280.&amp;lt;/ref&amp;gt;, усовершенствован J.C. Bezdek в 1981 г.&amp;lt;ref&amp;gt; Bezdek, James C. (1981). Pattern Recognition with Fuzzy Objective Function Algorithms. ISBN 0-306-40671-3.&amp;lt;/ref&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;
# Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим матрицу &amp;lt;math&amp;gt; M = m_{ik} \in[0,1],\;  i = 1, ..., c, \; k = 1, ..., K &amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;m_{i,k}&amp;lt;/math&amp;gt; - вероятность принадлежности объекта &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; - количество векторов. При этом элементы матрицы удовлетворяют следующим условиям:&lt;br /&gt;
&lt;br /&gt;
* сумма элементов в каждом столбце равна &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* сумма всех элементов матрицы равно &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Назовем &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; матрицей принадлежности.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; - центры кластеров. Тогда рассмотрим функцию &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
J(M, c_{1}, c_{2},...c_{c}) = \sum_{i = 1}^{c}{J_{i}} = \sum_{i = 1}^{c}\sum_{k = 1}^{K}{m_{ik}^q}d_{ik}^2 ~(1)&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt; d_{ik} = \left\Vert{u_{k}-c_{i}}\right\| &amp;lt;/math&amp;gt; - Евклидово расстояние между центром кластера и объектом, &amp;lt;math&amp;gt; 1 \le q \le \infty &amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость. Будем минимизировать значение функции &amp;lt;math&amp;gt; J &amp;lt;/math&amp;gt;. Для этого вычислим центры кластеров по формуле &amp;lt;math&amp;gt; ~(2) &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c_{i} = {{\sum_{k = 1}^{K}{m_{ik}^q} * u_{k}} \over {\sum_{k = 1}^{K}{m_{ik}^q}}}~(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;m_{ik}&amp;lt;/math&amp;gt; — коэффициент принадлежности &amp;lt;math&amp;gt;u_{k}&amp;lt;/math&amp;gt; вектора к кластеру &amp;lt;math&amp;gt;c_{i}&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
и новые значения матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; по формуле &amp;lt;math&amp;gt; ~(3) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;m_{ik} = {1 \over \sum_{j = 1}^{c}{({{d_{ik}} \over {d_{jk}}})}^{2 \over q-1}} ~(3)&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; ~(2) &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; ~(3) &amp;lt;/math&amp;gt;являются необходимым условиями достижения минимума функцией &amp;lt;math&amp;gt; J &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; случайными значениями от 0 до 1;&lt;br /&gt;
# Вычислить центры кластеров &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; используя формулу &amp;lt;math&amp;gt;~(2)&amp;lt;/math&amp;gt;;&lt;br /&gt;
# Вычислить значение решающей функции по формуле &amp;lt;math&amp;gt;~(1)&amp;lt;/math&amp;gt;. Если значение &amp;lt;math&amp;gt; J &amp;lt; \varepsilon,~\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt; |J_{i} - J_{i-1}| &amp;lt; \delta,~\delta &amp;gt; 0 &amp;lt;/math&amp;gt;, то остановить вычисления;&lt;br /&gt;
# Иначе вычислить новые значения матрицы М по формуле &amp;lt;math&amp;gt;~(3)&amp;lt;/math&amp;gt;;&lt;br /&gt;
# Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительным ядром алгоритма являются формулы: &amp;lt;math&amp;gt; (1) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (2) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (3) &amp;lt;/math&amp;gt;. В них производится вычисление новых центров кластеров, значения решающей функции и пересчет элементов матрицы принадлежности.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Макроструктура алгоритма состоит из следующих шагов:&lt;br /&gt;
&lt;br /&gt;
# Инициализация матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; случайными значениями от 0 до 1;&lt;br /&gt;
# Вычисление центров кластеров; &lt;br /&gt;
# Вычисление значения решающей функции(если оно удовлетворяет условиям останова - завершение вычислений);&lt;br /&gt;
# Вычисление новых элементов матрицы принадлежности;&lt;br /&gt;
# Переход к шагу 2;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации алгоритма на языке С++&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    float ** m;&lt;br /&gt;
    int *c;&lt;br /&gt;
    int number_clusters, number_items;&lt;br /&gt;
    m = gen_random_clusters();//заполним матрицу m случайными значениями от 0 до 1&lt;br /&gt;
    &lt;br /&gt;
    while (true)&lt;br /&gt;
    {&lt;br /&gt;
      //вычисление центров кластеров&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
        {&lt;br /&gt;
            numerator==denumerator=0;&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
            {&lt;br /&gt;
                numerator+=pow(m[i, k], q)*u[k];//u[k]-вектор&lt;br /&gt;
                denumerator+=pow(m[i, k], q);&lt;br /&gt;
            }&lt;br /&gt;
        c[i]= numerator / denumerator;//центры кластеров&lt;br /&gt;
        }&lt;br /&gt;
    &lt;br /&gt;
        j=0;//вычисление решающей функции&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
                j+=pow(m[i, k], q)*pow(dist(c[i], x[k],2);//dist-вычисляет расстояние между заданными векторами&lt;br /&gt;
    &lt;br /&gt;
       if ((abs(j-last_j)&amp;lt;delta) || (j&amp;lt;eps)) break;//проверка на необходимость завернешения алгоритма&lt;br /&gt;
       last_j=j;&lt;br /&gt;
     //обновление матрицы m&lt;br /&gt;
       for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
          for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
             {&lt;br /&gt;
               m[i,k]=0&lt;br /&gt;
              for(int j=0; j&amp;lt;number_clusters; j++)&lt;br /&gt;
                  m[i,k]+=pow(dist(c[i], x[k])/dist(c[j], x[k]),2/(q-1));&lt;br /&gt;
              m[i,k]=1/m[i,k];&lt;br /&gt;
              }&lt;br /&gt;
                                       &lt;br /&gt;
    }&lt;br /&gt;
    &amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Каждая итерация включает в себя&lt;br /&gt;
* Вычисление центров кластеров &amp;lt;math&amp;gt;O(C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
* Вычисление решающей функции &amp;lt;math&amp;gt;O(C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
* Обновлене матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;O(C*C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
Общая сложность каждой итерации &amp;lt;math&amp;gt;O(C*C*K)&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;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; параллельных операций, каждая их которых в свою очередь состоит из &amp;lt;math&amp;gt;K&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;C*K&amp;lt;/math&amp;gt; параллельных операций.&lt;br /&gt;
Результатом его работы является значение решающей функции &amp;lt;math&amp;gt;J&amp;lt;/math&amp;gt;. Её значение определяет необходимость завершения алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Третий ярус&#039;&#039;&#039; включает &amp;lt;math&amp;gt;C*K&amp;lt;/math&amp;gt; параллельных операций, каждая из которых состоит из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; параллельных операций, и одной, которая выполняется с использованием результата предыдущих.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Снимок экрана 2016-10-15 в 23.10.05.png|582 px|thumb|center|Информационный граф]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
На каждом шаге алгоритма необходимо вычислять сумму элементов массивов. Сложность ее вычисления на первом шаге (вычисление центров кластеров) при параллельной реализации составляет &amp;lt;math&amp;gt;O(\log_{2} C)&amp;lt;/math&amp;gt;. Для каждого элемента из набора входных данных(&amp;lt;math&amp;gt; K &amp;lt;/math&amp;gt;), но здесь возможен независимый расчет(координатный параллелизм). На втором шаге(вычисление решающей функции) сложность будет &amp;lt;math&amp;gt;O(\log_{2} {C*K})&amp;lt;/math&amp;gt;, потому что здесь необходимо сложение всех элементов. На третьем шаге имеем сложность &amp;lt;math&amp;gt;O(\log_{2} C^2)&amp;lt;/math&amp;gt;. Итого суммарная сложность итерации: &amp;lt;math&amp;gt;O(\log_{2} {C*K} + \log_{2} C^3)&amp;lt;/math&amp;gt;. Воспользовавшись свойствами логарифма произведения получаем: &amp;lt;math&amp;gt;O(\log_{2} {K} + \log_{2} C^4)&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Скошенного параллелизма в алгоритме нет.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Входные данные:&lt;br /&gt;
* &amp;lt;math&amp;gt;u_{k} ~k = 1, ..., K&amp;lt;/math&amp;gt; - набор входных векторов размерности &amp;lt;math&amp;gt; N &amp;lt;/math&amp;gt;;&lt;br /&gt;
* &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; - количество кластеров;&lt;br /&gt;
* &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость;&lt;br /&gt;
* &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0, ~\delta &amp;gt; 0&amp;lt;/math&amp;gt; - коэффициенты, описывающие точность алгоритма.&lt;br /&gt;
Объем входных данных: &amp;lt;math&amp;gt; K*N &amp;lt;/math&amp;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; C*K &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
*Соотношение последовательной и параллельной сложности алгоритма: &amp;lt;math&amp;gt;C*C*K \over {\log_{2} {K} + \log_{2} C^4}&amp;lt;/math&amp;gt;. Соответственно при распараллеливании наибольший прирост в производительности мы получим при разбиении большого набора данных на большее число кластеров;&lt;br /&gt;
*Вычислительная мощность: &amp;lt;math&amp;gt;{{C^2*K} \over {C*K}} = C&amp;lt;/math&amp;gt;. Получается, что на чем большее количество кластеров мы разбиваем набор данных, тем менее затратным становится перемещение данных;&lt;br /&gt;
*Алгоритм не является устойчивым, как и другие подобные алгоритмы этого класса(например k-means). Очень многое зависит как от входных данных, так и от изначальных параметров приближения(заполнения матрицы принадлежности =&amp;gt; исходных центров кластеров);&lt;br /&gt;
*Не является детерминированным. Так же очень многое зависит как от входных данных, так и от изначальных параметров приближения(заполнения матрицы принадлежности =&amp;gt; исходных центров кластеров);&lt;br /&gt;
*Алгоритм не сбалансирован - доминирует операция умножения. Параллельные ветви алгоритма сбалансированы;&lt;br /&gt;
*Степень исхода вершины информационного графа - 2.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Можно найти следующие реализации алгоритма&lt;br /&gt;
* Для MATLAB http://www.mathworks.com/help/fuzzy/fcm.html &lt;br /&gt;
* В PostgreSQL http://num-meth.srcc.msu.ru/zhurnal/tom_2012/v13r207.html&lt;br /&gt;
Так же готовые реализации алгоритма и его описание можно найти на сайтах&lt;br /&gt;
* https://habrahabr.ru/post/208496/&lt;br /&gt;
* http://pythonhosted.org/scikit-fuzzy/auto_examples/plot_cmeans.html&lt;br /&gt;
* http://www.codeproject.com/Articles/91675/Computer-Vision-Applications-with-C-Fuzzy-C-means&lt;br /&gt;
* https://github.com/gyaikhom/fcm&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>ADovganich</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=14545</id>
		<title>Участник:ADovganich/Нечеткий алгоритм С средних</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=14545"/>
		<updated>2016-10-28T15:20:16Z</updated>

		<summary type="html">&lt;p&gt;ADovganich: /* Общее описание алгоритма */&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(C*C*K*I)&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;K&amp;lt;/math&amp;gt;, [векторов]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;C*K&amp;lt;/math&amp;gt;, [элементы матрицы принадлежности]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;3I&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;C*C*K&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Protsenko|Мария Проценко]] (1.5-1.8, 2.7), [[Участник:ADovganich|Андрей Довганич]] (1.1-1.4, 1.9, 1.10)&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Нечеткий алгоритм C-средних (fuzzy C-means) позволяет разбить имеющееся множество векторов (точек) мощностью &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; на заданное число нечетких множеств. Предназначен для кластеризации больших наборов данных. Основным достоинством алгоритма является нечеткость при определении объекта в кластер. Благодаря этому становится возможным определить объекты, которые находятся на границе, в кластеры. Из основного достоинства следует и главный недостаток - неопределенность с объектами, удаленными от центров всех кластеров. В остальном ему присущи стандартные проблемы подобного класса алгоритмов: вычислительная сложность, необходимость задания количества кластеров&amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм был разработан J.C. Dunn в 1973 г.&amp;lt;ref&amp;gt; Dunn, J. C. (1973-01-01). &amp;quot;A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters&amp;quot;. Journal of Cybernetics. 3 (3): 32–57. doi:10.1080/01969727308546046. ISSN 0022-0280.&amp;lt;/ref&amp;gt;, усовершенствован J.C. Bezdek в 1981 г.&amp;lt;ref&amp;gt; Bezdek, James C. (1981). Pattern Recognition with Fuzzy Objective Function Algorithms. ISBN 0-306-40671-3.&amp;lt;/ref&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;
# Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим матрицу &amp;lt;math&amp;gt; M = m_{ik} \in[0,1],\;  i = 1, ..., c, \; k = 1, ..., K &amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;m_{i,k}&amp;lt;/math&amp;gt; - вероятность принадлежности объекта &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; - количество векторов. При этом элементы матрицы удовлетворяют следующим условиям:&lt;br /&gt;
&lt;br /&gt;
* сумма элементов в каждом столбце равна &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* сумма всех элементов матрицы равно &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Назовем &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; матрицей принадлежности.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; - центры кластеров. Тогда рассмотрим функцию &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
J(M, c_{1}, c_{2},...c_{c}) = \sum_{i = 1}^{c}{J_{i}} = \sum_{i = 1}^{c}\sum_{k = 1}^{K}{m_{ik}^q}d_{ik}^2 ~(1)&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt; d_{ik} = \left\Vert{u_{k}-c_{i}}\right\| &amp;lt;/math&amp;gt; - Евклидово расстояние между центром кластера и объектом, &amp;lt;math&amp;gt; 1 \le q \le \infty &amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость. Будем минимизировать значение функции &amp;lt;math&amp;gt; J &amp;lt;/math&amp;gt;. Для этого вычислим центры кластеров по формуле &amp;lt;math&amp;gt; ~(2) &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c_{i} = {{\sum_{k = 1}^{K}{m_{ik}^q} * u_{k}} \over {\sum_{k = 1}^{K}{m_{ik}^q}}}~(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;m_{ik}&amp;lt;/math&amp;gt; — коэффициент принадлежности &amp;lt;math&amp;gt;u_{k}&amp;lt;/math&amp;gt; вектора к кластеру &amp;lt;math&amp;gt;c_{i}&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
и новые значения матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; по формуле &amp;lt;math&amp;gt; ~(3) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;m_{ik} = {1 \over \sum_{j = 1}^{c}{({{d_{ik}} \over {d_{jk}}})}^{2 \over q-1}} ~(3)&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; ~(2) &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; ~(3) &amp;lt;/math&amp;gt;являются необходимым условиями достижения минимума функцией &amp;lt;math&amp;gt; J &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; случайными значениями от 0 до 1;&lt;br /&gt;
# Вычислить центры кластеров &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; используя формулу &amp;lt;math&amp;gt;~(2)&amp;lt;/math&amp;gt;;&lt;br /&gt;
# Вычислить значение решающей функции по формуле &amp;lt;math&amp;gt;~(1)&amp;lt;/math&amp;gt;. Если значение &amp;lt;math&amp;gt; J &amp;lt; \varepsilon,~\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt; |J_{i} - J_{i-1}| &amp;lt; \delta,~\delta &amp;gt; 0 &amp;lt;/math&amp;gt;, то остановить вычисления;&lt;br /&gt;
# Иначе вычислить новые значения матрицы М по формуле &amp;lt;math&amp;gt;~(3)&amp;lt;/math&amp;gt;;&lt;br /&gt;
# Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительным ядром алгоритма являются формулы: &amp;lt;math&amp;gt; (1) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (2) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (3) &amp;lt;/math&amp;gt;. В них производится вычисление новых центров кластеров, значения решающей функции и пересчет элементов матрицы принадлежности.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Макроструктура алгоритма состоит из следующих шагов:&lt;br /&gt;
&lt;br /&gt;
# Инициализация матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; случайными значениями от 0 до 1;&lt;br /&gt;
# Вычисление центров кластеров; &lt;br /&gt;
# Вычисление значения решающей функции(если оно удовлетворяет условиям останова - завершение вычислений);&lt;br /&gt;
# Вычисление новых элементов матрицы принадлежности;&lt;br /&gt;
# Переход к шагу 2;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации алгоритма на языке С++&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    float ** m;&lt;br /&gt;
    int *c;&lt;br /&gt;
    int number_clusters, number_items;&lt;br /&gt;
    m = gen_random_clusters();//заполним матрицу m случайными значениями от 0 до 1&lt;br /&gt;
    &lt;br /&gt;
    while (true)&lt;br /&gt;
    {&lt;br /&gt;
      //вычисление центров кластеров&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
        {&lt;br /&gt;
            numerator==denumerator=0;&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
            {&lt;br /&gt;
                numerator+=pow(m[i, k], q)*u[k];//u[k]-вектор&lt;br /&gt;
                denumerator+=pow(m[i, k], q);&lt;br /&gt;
            }&lt;br /&gt;
        c[i]= numerator / denumerator;//центры кластеров&lt;br /&gt;
        }&lt;br /&gt;
    &lt;br /&gt;
        j=0;//вычисление решающей функции&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
                j+=pow(m[i, k], q)*pow(dist(c[i], x[k],2);//dist-вычисляет расстояние между заданными векторами&lt;br /&gt;
    &lt;br /&gt;
       if ((abs(j-last_j)&amp;lt;delta) || (j&amp;lt;eps)) break;//проверка на необходимость завернешения алгоритма&lt;br /&gt;
       last_j=j;&lt;br /&gt;
     //обновление матрицы m&lt;br /&gt;
       for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
          for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
             {&lt;br /&gt;
               m[i,k]=0&lt;br /&gt;
              for(int j=0; j&amp;lt;number_clusters; j++)&lt;br /&gt;
                  m[i,k]+=pow(dist(c[i], x[k])/dist(c[j], x[k]),2/(q-1));&lt;br /&gt;
              m[i,k]=1/m[i,k];&lt;br /&gt;
              }&lt;br /&gt;
                                       &lt;br /&gt;
    }&lt;br /&gt;
    &amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Каждая итерация включает в себя&lt;br /&gt;
* Вычисление центров кластеров &amp;lt;math&amp;gt;O(C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
* Вычисление решающей функции &amp;lt;math&amp;gt;O(C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
* Обновлене матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;O(C*C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
Общая сложность каждой итерации &amp;lt;math&amp;gt;O(C*C*K)&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;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; параллельных операций, каждая их которых в свою очередь состоит из &amp;lt;math&amp;gt;K&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;C*K&amp;lt;/math&amp;gt; параллельных операций.&lt;br /&gt;
Результатом его работы является значение решающей функции &amp;lt;math&amp;gt;J&amp;lt;/math&amp;gt;. Её значение определяет необходимость завершения алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Третий ярус&#039;&#039;&#039; включает &amp;lt;math&amp;gt;C*K&amp;lt;/math&amp;gt; параллельных операций, каждая из которых состоит из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; параллельных операций, и одной, которая выполняется с использованием результата предыдущих.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Снимок экрана 2016-10-15 в 23.10.05.png|582 px|thumb|center|Информационный граф]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
На каждом шаге алгоритма необходимо вычислять сумму элементов массивов. Сложность ее вычисления на первом шаге (вычисление центров кластеров) при параллельной реализации составляет &amp;lt;math&amp;gt;O(\log_{2} C)&amp;lt;/math&amp;gt;. Для каждого элемента из набора входных данных(&amp;lt;math&amp;gt; K &amp;lt;/math&amp;gt;), но здесь возможен независимый расчет(координатный параллелизм). На втором шаге(вычисление решающей функции) сложность будет &amp;lt;math&amp;gt;O(\log_{2} {C*K})&amp;lt;/math&amp;gt;, потому что здесь необходимо сложение всех элементов. На третьем шаге имеем сложность &amp;lt;math&amp;gt;O(\log_{2} C^2)&amp;lt;/math&amp;gt;. Итого суммарная сложность итерации: &amp;lt;math&amp;gt;O(\log_{2} {C*K} + \log_{2} C^3)&amp;lt;/math&amp;gt;. Воспользовавшись свойствами логарифма произведения получаем: &amp;lt;math&amp;gt;O(\log_{2} {K} + \log_{2} C^4)&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Скошенного параллелизма в алгоритме нет.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Входные данные:&lt;br /&gt;
* &amp;lt;math&amp;gt;u_{k} ~k = 1, ..., K&amp;lt;/math&amp;gt; - набор входных векторов;&lt;br /&gt;
* &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; - количество кластеров;&lt;br /&gt;
* &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость;&lt;br /&gt;
* &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0, ~\delta &amp;gt; 0&amp;lt;/math&amp;gt; - коэффициенты, описывающие точность алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные:&lt;br /&gt;
* &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; - матрица принадлежности.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
*Соотношение последовательной и параллельной сложности алгоритма: &amp;lt;math&amp;gt;C*C*K \over {\log_{2} {K} + \log_{2} C^4}&amp;lt;/math&amp;gt;. Соответственно при распараллеливании наибольший прирост в производительности мы получим при разбиении большого набора данных на большее число кластеров;&lt;br /&gt;
*Вычислительная мощность: &amp;lt;math&amp;gt;{{C^2*K} \over {C*K}} = C&amp;lt;/math&amp;gt;. Получается, что на чем большее количество кластеров мы разбиваем набор данных, тем менее затратным становится перемещение данных;&lt;br /&gt;
*Алгоритм не является устойчивым, как и другие подобные алгоритмы этого класса(например k-means). Очень многое зависит как от входных данных, так и от изначальных параметров приближения(заполнения матрицы принадлежности =&amp;gt; исходных центров кластеров);&lt;br /&gt;
*Не является детерминированным. Так же очень многое зависит как от входных данных, так и от изначальных параметров приближения(заполнения матрицы принадлежности =&amp;gt; исходных центров кластеров);&lt;br /&gt;
*Алгоритм не сбалансирован - доминирует операция умножения. Параллельные ветви алгоритма сбалансированы;&lt;br /&gt;
*Степень исхода вершины информационного графа - 2.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Можно найти следующие реализации алгоритма&lt;br /&gt;
* Для MATLAB http://www.mathworks.com/help/fuzzy/fcm.html &lt;br /&gt;
* В PostgreSQL http://num-meth.srcc.msu.ru/zhurnal/tom_2012/v13r207.html&lt;br /&gt;
Так же готовые реализации алгоритма и его описание можно найти на сайтах&lt;br /&gt;
* https://habrahabr.ru/post/208496/&lt;br /&gt;
* http://pythonhosted.org/scikit-fuzzy/auto_examples/plot_cmeans.html&lt;br /&gt;
* http://www.codeproject.com/Articles/91675/Computer-Vision-Applications-with-C-Fuzzy-C-means&lt;br /&gt;
* https://github.com/gyaikhom/fcm&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>ADovganich</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=14544</id>
		<title>Участник:ADovganich/Нечеткий алгоритм С средних</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=14544"/>
		<updated>2016-10-28T15:20:01Z</updated>

		<summary type="html">&lt;p&gt;ADovganich: /* Общее описание алгоритма */&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(C*C*K*I)&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;K&amp;lt;/math&amp;gt;, [векторов]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;C*K&amp;lt;/math&amp;gt;, [элементы матрицы принадлежности]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;3I&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;C*C*K&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Protsenko|Мария Проценко]] (1.5-1.8, 2.7), [[Участник:ADovganich|Андрей Довганич]] (1.1-1.4, 1.9, 1.10)&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Нечеткий алгоритм C-средних (fuzzy C-means) позволяет разбить имеющееся множество векторов (точек) мощностью &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; на заданное число нечетких множеств. Предназначен для кластеризации больших наборов данных. Основным достоинством алгоритма является нечеткость при определении объекта в кластер. Благодаря этому становится возможным определить объекты, которые находятся на границе, в кластеры. Из основного достоинства следует и главный недостаток - неопределенность с объектами, удаленными от центров всех кластеров. В остальном ему присущи стандартные проблемы подобного класса алгоритмов: вычислительная сложность, необходимость задания количества кластеров&amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм был разработан J.C. Dunn в 1973 г.&amp;lt;ref&amp;gt; Dunn, J. C. (1973-01-01). &amp;quot;A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters&amp;quot;. Journal of Cybernetics. 3 (3): 32–57. doi:10.1080/01969727308546046. ISSN 0022-0280.&amp;lt;/ref&amp;gt;, усовершенствован J.C. Bezdek в 1981 г.&amp;lt;ref&amp;gt; Bezdek, James C. (1981). Pattern Recognition with Fuzzy Objective Function Algorithms. ISBN 0-306-40671-3.&amp;lt;/ref&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;
# Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим матрицу &amp;lt;math&amp;gt; M = m_{ik} \in[0,1],\;  i = 1, ..., c, \; k = 1, ..., K &amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;m_{i,k}&amp;lt;/math&amp;gt; - вероятность принадлежности объекта &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; - количество векторов. При этом элементы матрицы удовлетворяют следующим условиям:&lt;br /&gt;
&lt;br /&gt;
* сумма элементов в каждом столбце равна &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* сумма всех элементов матрицы равно &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Назовем &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; матрицей принадлежности.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; - центры кластеров. Тогда рассмотрим функцию &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
J(M, c_{1}, c_{2},...c_{c}) = \sum_{i = 1}^{c}{J_{i}} = \sum_{i = 1}^{c}\sum_{k = 1}^{K}{m_{ik}^q}d_{ik}^2 ~(1)&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt; d_{ik} = \left\Vert{u_{k}-c_{i}}\right\| &amp;lt;/math&amp;gt; - Евклидово расстояние между центром кластера и объектом, &amp;lt;math&amp;gt; 1 \le q \le \infty &amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость. Будем минимизировать значение функции &amp;lt;math&amp;gt; J &amp;lt;/math&amp;gt;. Для этого вычислим центры кластеров по формуле &amp;lt;math&amp;gt; ~(2) &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c_{i} = {{\sum_{k = 1}^{K}{m_{ik}^q} * u_{k}} \over {\sum_{k = 1}^{K}{m_{ik}^q}}}~(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;m_{ik}&amp;lt;/math&amp;gt; — коэффициент принадлежности &amp;lt;math&amp;gt;u_{k}&amp;lt;/math&amp;gt; вектора к кластеру &amp;lt;math&amp;gt;c_{i}&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
и новые значения матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; по формуле &amp;lt;math&amp;gt; ~(3) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;m_{ik} = {1 \over \sum_{j = 1}^{c}{({{d_{ik}} \over {d_{jk}}})}^{2 \over q-1}} ~(3)&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; ~(2) &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; ~(3) &amp;lt;/math&amp;gt;являются необходимым условиями достижения минимума функцией &amp;lt;math&amp;gt; J &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; случайными значениями от 0 до 1;&lt;br /&gt;
# Вычислить центры кластеров &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; используя формулу &amp;lt;math&amp;gt;~(2)&amp;lt;/math&amp;gt;;&lt;br /&gt;
# Вычислить значение решающей функции по формуле &amp;lt;math&amp;gt;~(1)&amp;lt;/math&amp;gt;. Если значение &amp;lt;math&amp;gt; J &amp;lt; \varepsilon,~\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt; |J_{i} - J_{i-1}| &amp;lt; \delta,~\delta &amp;gt; 0 &amp;lt;/math&amp;gt;, то остановить вычисления;&lt;br /&gt;
# Иначе вычислить новые значения матрицы М по формуле &amp;lt;math&amp;gt;~(3)&amp;lt;/math&amp;gt;;&lt;br /&gt;
# Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительным ядром алгоритма являются формулы: &amp;lt;math&amp;gt; (1) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (2) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (3) &amp;lt;/math&amp;gt;. В них производится вычисление новых центров кластеров, значения решающей функции и пересчет элементов матрицы принадлежности.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Макроструктура алгоритма состоит из следующих шагов:&lt;br /&gt;
&lt;br /&gt;
# Инициализация матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; случайными значениями от 0 до 1;&lt;br /&gt;
# Вычисление центров кластеров; &lt;br /&gt;
# Вычисление значения решающей функции(если оно удовлетворяет условиям останова - завершение вычислений);&lt;br /&gt;
# Вычисление новых элементов матрицы принадлежности;&lt;br /&gt;
# Переход к шагу 2;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации алгоритма на языке С++&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    float ** m;&lt;br /&gt;
    int *c;&lt;br /&gt;
    int number_clusters, number_items;&lt;br /&gt;
    m = gen_random_clusters();//заполним матрицу m случайными значениями от 0 до 1&lt;br /&gt;
    &lt;br /&gt;
    while (true)&lt;br /&gt;
    {&lt;br /&gt;
      //вычисление центров кластеров&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
        {&lt;br /&gt;
            numerator==denumerator=0;&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
            {&lt;br /&gt;
                numerator+=pow(m[i, k], q)*u[k];//u[k]-вектор&lt;br /&gt;
                denumerator+=pow(m[i, k], q);&lt;br /&gt;
            }&lt;br /&gt;
        c[i]= numerator / denumerator;//центры кластеров&lt;br /&gt;
        }&lt;br /&gt;
    &lt;br /&gt;
        j=0;//вычисление решающей функции&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
                j+=pow(m[i, k], q)*pow(dist(c[i], x[k],2);//dist-вычисляет расстояние между заданными векторами&lt;br /&gt;
    &lt;br /&gt;
       if ((abs(j-last_j)&amp;lt;delta) || (j&amp;lt;eps)) break;//проверка на необходимость завернешения алгоритма&lt;br /&gt;
       last_j=j;&lt;br /&gt;
     //обновление матрицы m&lt;br /&gt;
       for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
          for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
             {&lt;br /&gt;
               m[i,k]=0&lt;br /&gt;
              for(int j=0; j&amp;lt;number_clusters; j++)&lt;br /&gt;
                  m[i,k]+=pow(dist(c[i], x[k])/dist(c[j], x[k]),2/(q-1));&lt;br /&gt;
              m[i,k]=1/m[i,k];&lt;br /&gt;
              }&lt;br /&gt;
                                       &lt;br /&gt;
    }&lt;br /&gt;
    &amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Каждая итерация включает в себя&lt;br /&gt;
* Вычисление центров кластеров &amp;lt;math&amp;gt;O(C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
* Вычисление решающей функции &amp;lt;math&amp;gt;O(C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
* Обновлене матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;O(C*C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
Общая сложность каждой итерации &amp;lt;math&amp;gt;O(C*C*K)&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;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; параллельных операций, каждая их которых в свою очередь состоит из &amp;lt;math&amp;gt;K&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;C*K&amp;lt;/math&amp;gt; параллельных операций.&lt;br /&gt;
Результатом его работы является значение решающей функции &amp;lt;math&amp;gt;J&amp;lt;/math&amp;gt;. Её значение определяет необходимость завершения алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Третий ярус&#039;&#039;&#039; включает &amp;lt;math&amp;gt;C*K&amp;lt;/math&amp;gt; параллельных операций, каждая из которых состоит из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; параллельных операций, и одной, которая выполняется с использованием результата предыдущих.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Снимок экрана 2016-10-15 в 23.10.05.png|582 px|thumb|center|Информационный граф]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
На каждом шаге алгоритма необходимо вычислять сумму элементов массивов. Сложность ее вычисления на первом шаге (вычисление центров кластеров) при параллельной реализации составляет &amp;lt;math&amp;gt;O(\log_{2} C)&amp;lt;/math&amp;gt;. Для каждого элемента из набора входных данных(&amp;lt;math&amp;gt; K &amp;lt;/math&amp;gt;), но здесь возможен независимый расчет(координатный параллелизм). На втором шаге(вычисление решающей функции) сложность будет &amp;lt;math&amp;gt;O(\log_{2} {C*K})&amp;lt;/math&amp;gt;, потому что здесь необходимо сложение всех элементов. На третьем шаге имеем сложность &amp;lt;math&amp;gt;O(\log_{2} C^2)&amp;lt;/math&amp;gt;. Итого суммарная сложность итерации: &amp;lt;math&amp;gt;O(\log_{2} {C*K} + \log_{2} C^3)&amp;lt;/math&amp;gt;. Воспользовавшись свойствами логарифма произведения получаем: &amp;lt;math&amp;gt;O(\log_{2} {K} + \log_{2} C^4)&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Скошенного параллелизма в алгоритме нет.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Входные данные:&lt;br /&gt;
* &amp;lt;math&amp;gt;u_{k} ~k = 1, ..., K&amp;lt;/math&amp;gt; - набор входных векторов;&lt;br /&gt;
* &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; - количество кластеров;&lt;br /&gt;
* &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость;&lt;br /&gt;
* &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0, ~\delta &amp;gt; 0&amp;lt;/math&amp;gt; - коэффициенты, описывающие точность алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные:&lt;br /&gt;
* &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; - матрица принадлежности.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
*Соотношение последовательной и параллельной сложности алгоритма: &amp;lt;math&amp;gt;C*C*K \over {\log_{2} {K} + \log_{2} C^4}&amp;lt;/math&amp;gt;. Соответственно при распараллеливании наибольший прирост в производительности мы получим при разбиении большого набора данных на большее число кластеров;&lt;br /&gt;
*Вычислительная мощность: &amp;lt;math&amp;gt;{{C^2*K} \over {C*K}} = C&amp;lt;/math&amp;gt;. Получается, что на чем большее количество кластеров мы разбиваем набор данных, тем менее затратным становится перемещение данных;&lt;br /&gt;
*Алгоритм не является устойчивым, как и другие подобные алгоритмы этого класса(например k-means). Очень многое зависит как от входных данных, так и от изначальных параметров приближения(заполнения матрицы принадлежности =&amp;gt; исходных центров кластеров);&lt;br /&gt;
*Не является детерминированным. Так же очень многое зависит как от входных данных, так и от изначальных параметров приближения(заполнения матрицы принадлежности =&amp;gt; исходных центров кластеров);&lt;br /&gt;
*Алгоритм не сбалансирован - доминирует операция умножения. Параллельные ветви алгоритма сбалансированы;&lt;br /&gt;
*Степень исхода вершины информационного графа - 2.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Можно найти следующие реализации алгоритма&lt;br /&gt;
* Для MATLAB http://www.mathworks.com/help/fuzzy/fcm.html &lt;br /&gt;
* В PostgreSQL http://num-meth.srcc.msu.ru/zhurnal/tom_2012/v13r207.html&lt;br /&gt;
Так же готовые реализации алгоритма и его описание можно найти на сайтах&lt;br /&gt;
* https://habrahabr.ru/post/208496/&lt;br /&gt;
* http://pythonhosted.org/scikit-fuzzy/auto_examples/plot_cmeans.html&lt;br /&gt;
* http://www.codeproject.com/Articles/91675/Computer-Vision-Applications-with-C-Fuzzy-C-means&lt;br /&gt;
* https://github.com/gyaikhom/fcm&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>ADovganich</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=14543</id>
		<title>Участник:ADovganich/Нечеткий алгоритм С средних</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=14543"/>
		<updated>2016-10-28T15:13:44Z</updated>

		<summary type="html">&lt;p&gt;ADovganich: /* Входные и выходные данные алгоритма */&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(C*C*K*I)&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;K&amp;lt;/math&amp;gt;, [векторов]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;C*K&amp;lt;/math&amp;gt;, [элементы матрицы принадлежности]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;3I&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;C*C*K&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Protsenko|Мария Проценко]] (1.5-1.8, 2.7), [[Участник:ADovganich|Андрей Довганич]] (1.1-1.4, 1.9, 1.10)&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Нечеткий алгоритм C-средних (fuzzy C-means) позволяет разбить имеющееся множество векторов (точек) мощностью K на заданное число нечетких множеств. Предназначен для кластеризации больших наборов данных. Основным достоинством алгоритма является нечеткость при определении объекта в кластер. Благодаря этому становится возможным определить объекты, которые находятся на границе, в кластеры. Из основного достоинства следует и главный недостаток - неопределенность с объектами, удаленными от центров всех кластеров. В остальном ему присущи стандартные проблемы подобного класса алгоритмов: вычислительная сложность, необходимость задания количества кластеров&amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм был разработан J.C. Dunn в 1973 г.&amp;lt;ref&amp;gt; Dunn, J. C. (1973-01-01). &amp;quot;A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters&amp;quot;. Journal of Cybernetics. 3 (3): 32–57. doi:10.1080/01969727308546046. ISSN 0022-0280.&amp;lt;/ref&amp;gt;, усовершенствован J.C. Bezdek в 1981 г.&amp;lt;ref&amp;gt; Bezdek, James C. (1981). Pattern Recognition with Fuzzy Objective Function Algorithms. ISBN 0-306-40671-3.&amp;lt;/ref&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;
# Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим матрицу &amp;lt;math&amp;gt; M = m_{ik} \in[0,1],\;  i = 1, ..., c, \; k = 1, ..., K &amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;m_{i,k}&amp;lt;/math&amp;gt; - вероятность принадлежности объекта &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; - количество векторов. При этом элементы матрицы удовлетворяют следующим условиям:&lt;br /&gt;
&lt;br /&gt;
* сумма элементов в каждом столбце равна &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* сумма всех элементов матрицы равно &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Назовем &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; матрицей принадлежности.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; - центры кластеров. Тогда рассмотрим функцию &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
J(M, c_{1}, c_{2},...c_{c}) = \sum_{i = 1}^{c}{J_{i}} = \sum_{i = 1}^{c}\sum_{k = 1}^{K}{m_{ik}^q}d_{ik}^2 ~(1)&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt; d_{ik} = \left\Vert{u_{k}-c_{i}}\right\| &amp;lt;/math&amp;gt; - Евклидово расстояние между центром кластера и объектом, &amp;lt;math&amp;gt; 1 \le q \le \infty &amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость. Будем минимизировать значение функции &amp;lt;math&amp;gt; J &amp;lt;/math&amp;gt;. Для этого вычислим центры кластеров по формуле &amp;lt;math&amp;gt; ~(2) &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c_{i} = {{\sum_{k = 1}^{K}{m_{ik}^q} * u_{k}} \over {\sum_{k = 1}^{K}{m_{ik}^q}}}~(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;m_{ik}&amp;lt;/math&amp;gt; — коэффициент принадлежности &amp;lt;math&amp;gt;u_{k}&amp;lt;/math&amp;gt; вектора к кластеру &amp;lt;math&amp;gt;c_{i}&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
и новые значения матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; по формуле &amp;lt;math&amp;gt; ~(3) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;m_{ik} = {1 \over \sum_{j = 1}^{c}{({{d_{ik}} \over {d_{jk}}})}^{2 \over q-1}} ~(3)&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; ~(2) &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; ~(3) &amp;lt;/math&amp;gt;являются необходимым условиями достижения минимума функцией &amp;lt;math&amp;gt; J &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; случайными значениями от 0 до 1;&lt;br /&gt;
# Вычислить центры кластеров &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; используя формулу &amp;lt;math&amp;gt;~(2)&amp;lt;/math&amp;gt;;&lt;br /&gt;
# Вычислить значение решающей функции по формуле &amp;lt;math&amp;gt;~(1)&amp;lt;/math&amp;gt;. Если значение &amp;lt;math&amp;gt; J &amp;lt; \varepsilon,~\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt; |J_{i} - J_{i-1}| &amp;lt; \delta,~\delta &amp;gt; 0 &amp;lt;/math&amp;gt;, то остановить вычисления;&lt;br /&gt;
# Иначе вычислить новые значения матрицы М по формуле &amp;lt;math&amp;gt;~(3)&amp;lt;/math&amp;gt;;&lt;br /&gt;
# Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительным ядром алгоритма являются формулы: &amp;lt;math&amp;gt; (1) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (2) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (3) &amp;lt;/math&amp;gt;. В них производится вычисление новых центров кластеров, значения решающей функции и пересчет элементов матрицы принадлежности.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Макроструктура алгоритма состоит из следующих шагов:&lt;br /&gt;
&lt;br /&gt;
# Инициализация матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; случайными значениями от 0 до 1;&lt;br /&gt;
# Вычисление центров кластеров; &lt;br /&gt;
# Вычисление значения решающей функции(если оно удовлетворяет условиям останова - завершение вычислений);&lt;br /&gt;
# Вычисление новых элементов матрицы принадлежности;&lt;br /&gt;
# Переход к шагу 2;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации алгоритма на языке С++&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    float ** m;&lt;br /&gt;
    int *c;&lt;br /&gt;
    int number_clusters, number_items;&lt;br /&gt;
    m = gen_random_clusters();//заполним матрицу m случайными значениями от 0 до 1&lt;br /&gt;
    &lt;br /&gt;
    while (true)&lt;br /&gt;
    {&lt;br /&gt;
      //вычисление центров кластеров&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
        {&lt;br /&gt;
            numerator==denumerator=0;&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
            {&lt;br /&gt;
                numerator+=pow(m[i, k], q)*u[k];//u[k]-вектор&lt;br /&gt;
                denumerator+=pow(m[i, k], q);&lt;br /&gt;
            }&lt;br /&gt;
        c[i]= numerator / denumerator;//центры кластеров&lt;br /&gt;
        }&lt;br /&gt;
    &lt;br /&gt;
        j=0;//вычисление решающей функции&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
                j+=pow(m[i, k], q)*pow(dist(c[i], x[k],2);//dist-вычисляет расстояние между заданными векторами&lt;br /&gt;
    &lt;br /&gt;
       if ((abs(j-last_j)&amp;lt;delta) || (j&amp;lt;eps)) break;//проверка на необходимость завернешения алгоритма&lt;br /&gt;
       last_j=j;&lt;br /&gt;
     //обновление матрицы m&lt;br /&gt;
       for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
          for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
             {&lt;br /&gt;
               m[i,k]=0&lt;br /&gt;
              for(int j=0; j&amp;lt;number_clusters; j++)&lt;br /&gt;
                  m[i,k]+=pow(dist(c[i], x[k])/dist(c[j], x[k]),2/(q-1));&lt;br /&gt;
              m[i,k]=1/m[i,k];&lt;br /&gt;
              }&lt;br /&gt;
                                       &lt;br /&gt;
    }&lt;br /&gt;
    &amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Каждая итерация включает в себя&lt;br /&gt;
* Вычисление центров кластеров &amp;lt;math&amp;gt;O(C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
* Вычисление решающей функции &amp;lt;math&amp;gt;O(C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
* Обновлене матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;O(C*C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
Общая сложность каждой итерации &amp;lt;math&amp;gt;O(C*C*K)&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;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; параллельных операций, каждая их которых в свою очередь состоит из &amp;lt;math&amp;gt;K&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;C*K&amp;lt;/math&amp;gt; параллельных операций.&lt;br /&gt;
Результатом его работы является значение решающей функции &amp;lt;math&amp;gt;J&amp;lt;/math&amp;gt;. Её значение определяет необходимость завершения алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Третий ярус&#039;&#039;&#039; включает &amp;lt;math&amp;gt;C*K&amp;lt;/math&amp;gt; параллельных операций, каждая из которых состоит из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; параллельных операций, и одной, которая выполняется с использованием результата предыдущих.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Снимок экрана 2016-10-15 в 23.10.05.png|582 px|thumb|center|Информационный граф]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
На каждом шаге алгоритма необходимо вычислять сумму элементов массивов. Сложность ее вычисления на первом шаге (вычисление центров кластеров) при параллельной реализации составляет &amp;lt;math&amp;gt;O(\log_{2} C)&amp;lt;/math&amp;gt;. Для каждого элемента из набора входных данных(&amp;lt;math&amp;gt; K &amp;lt;/math&amp;gt;), но здесь возможен независимый расчет(координатный параллелизм). На втором шаге(вычисление решающей функции) сложность будет &amp;lt;math&amp;gt;O(\log_{2} {C*K})&amp;lt;/math&amp;gt;, потому что здесь необходимо сложение всех элементов. На третьем шаге имеем сложность &amp;lt;math&amp;gt;O(\log_{2} C^2)&amp;lt;/math&amp;gt;. Итого суммарная сложность итерации: &amp;lt;math&amp;gt;O(\log_{2} {C*K} + \log_{2} C^3)&amp;lt;/math&amp;gt;. Воспользовавшись свойствами логарифма произведения получаем: &amp;lt;math&amp;gt;O(\log_{2} {K} + \log_{2} C^4)&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Скошенного параллелизма в алгоритме нет.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Входные данные:&lt;br /&gt;
* &amp;lt;math&amp;gt;u_{k} ~k = 1, ..., K&amp;lt;/math&amp;gt; - набор входных векторов;&lt;br /&gt;
* &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; - количество кластеров;&lt;br /&gt;
* &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость;&lt;br /&gt;
* &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0, ~\delta &amp;gt; 0&amp;lt;/math&amp;gt; - коэффициенты, описывающие точность алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные:&lt;br /&gt;
* &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; - матрица принадлежности.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
*Соотношение последовательной и параллельной сложности алгоритма: &amp;lt;math&amp;gt;C*C*K \over {\log_{2} {K} + \log_{2} C^4}&amp;lt;/math&amp;gt;. Соответственно при распараллеливании наибольший прирост в производительности мы получим при разбиении большого набора данных на большее число кластеров;&lt;br /&gt;
*Вычислительная мощность: &amp;lt;math&amp;gt;{{C^2*K} \over {C*K}} = C&amp;lt;/math&amp;gt;. Получается, что на чем большее количество кластеров мы разбиваем набор данных, тем менее затратным становится перемещение данных;&lt;br /&gt;
*Алгоритм не является устойчивым, как и другие подобные алгоритмы этого класса(например k-means). Очень многое зависит как от входных данных, так и от изначальных параметров приближения(заполнения матрицы принадлежности =&amp;gt; исходных центров кластеров);&lt;br /&gt;
*Не является детерминированным. Так же очень многое зависит как от входных данных, так и от изначальных параметров приближения(заполнения матрицы принадлежности =&amp;gt; исходных центров кластеров);&lt;br /&gt;
*Алгоритм не сбалансирован - доминирует операция умножения. Параллельные ветви алгоритма сбалансированы;&lt;br /&gt;
*Степень исхода вершины информационного графа - 2.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Можно найти следующие реализации алгоритма&lt;br /&gt;
* Для MATLAB http://www.mathworks.com/help/fuzzy/fcm.html &lt;br /&gt;
* В PostgreSQL http://num-meth.srcc.msu.ru/zhurnal/tom_2012/v13r207.html&lt;br /&gt;
Так же готовые реализации алгоритма и его описание можно найти на сайтах&lt;br /&gt;
* https://habrahabr.ru/post/208496/&lt;br /&gt;
* http://pythonhosted.org/scikit-fuzzy/auto_examples/plot_cmeans.html&lt;br /&gt;
* http://www.codeproject.com/Articles/91675/Computer-Vision-Applications-with-C-Fuzzy-C-means&lt;br /&gt;
* https://github.com/gyaikhom/fcm&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>ADovganich</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=12137</id>
		<title>Участник:ADovganich/Нечеткий алгоритм С средних</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=12137"/>
		<updated>2016-10-15T21:20:21Z</updated>

		<summary type="html">&lt;p&gt;ADovganich: &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(C*C*K*I)&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;K&amp;lt;/math&amp;gt;, [векторов]&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;C*K&amp;lt;/math&amp;gt;, [элементы матрицы принадлежности]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;3I&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;C*C*K&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Protsenko|Мария Проценко]] (1.5-1.8, 2.7), [[Участник:ADovganich|Андрей Довганич]] (1.1-1.4, 1.9, 1.10)&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Нечеткий алгоритм C-средних (fuzzy C-means) позволяет разбить имеющееся множество векторов (точек) мощностью K на заданное число нечетких множеств. Предназначен для кластеризации больших наборов данных. Основным достоинством алгоритма является нечеткость при определении объекта в кластер. Благодаря этому становится возможным определить объекты, которые находятся на границе, в кластеры. Из основного достоинства следует и главный недостаток - неопределенность с объектами, удаленными от центров всех кластеров. В остальном ему присущи стандартные проблемы подобного класса алгоритмов: вычислительная сложность, необходимость задания количества кластеров&amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм был разработан J.C. Dunn в 1973 г.&amp;lt;ref&amp;gt; Dunn, J. C. (1973-01-01). &amp;quot;A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters&amp;quot;. Journal of Cybernetics. 3 (3): 32–57. doi:10.1080/01969727308546046. ISSN 0022-0280.&amp;lt;/ref&amp;gt;, усовершенствован J.C. Bezdek в 1981 г.&amp;lt;ref&amp;gt; Bezdek, James C. (1981). Pattern Recognition with Fuzzy Objective Function Algorithms. ISBN 0-306-40671-3.&amp;lt;/ref&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;
# Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим матрицу &amp;lt;math&amp;gt; M = m_{ik} \in[0,1],\;  i = 1, ..., c, \; k = 1, ..., K &amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;m_{i,k}&amp;lt;/math&amp;gt; - вероятность принадлежности объекта &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; - количество векторов. При этом элементы матрицы удовлетворяют следующим условиям:&lt;br /&gt;
&lt;br /&gt;
* сумма элементов в каждом столбце равна &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* сумма всех элементов матрицы равно &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Назовем &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; матрицей принадлежности.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; - центры кластеров. Тогда рассмотрим функцию &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
J(M, c_{1}, c_{2},...c_{c}) = \sum_{i = 1}^{c}{J_{i}} = \sum_{i = 1}^{c}\sum_{k = 1}^{K}{m_{ik}^q}d_{ik}^2 ~(1)&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt; d_{ik} = \left\Vert{u_{k}-c_{i}}\right\| &amp;lt;/math&amp;gt; - Евклидово расстояние между центром кластера и объектом, &amp;lt;math&amp;gt; 1 \le q \le \infty &amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость. Будем минимизировать значение функции &amp;lt;math&amp;gt; J &amp;lt;/math&amp;gt;. Для этого вычислим центры кластеров по формуле &amp;lt;math&amp;gt; ~(2) &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c_{i} = {{\sum_{k = 1}^{K}{m_{ik}^q} * u_{k}} \over {\sum_{k = 1}^{K}{m_{ik}^q}}}~(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;m_{ik}&amp;lt;/math&amp;gt; — коэффициент принадлежности &amp;lt;math&amp;gt;u_{k}&amp;lt;/math&amp;gt; вектора к кластеру &amp;lt;math&amp;gt;c_{i}&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
и новые значения матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; по формуле &amp;lt;math&amp;gt; ~(3) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;m_{ik} = {1 \over \sum_{j = 1}^{c}{({{d_{ik}} \over {d_{jk}}})}^{2 \over q-1}} ~(3)&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; ~(2) &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; ~(3) &amp;lt;/math&amp;gt;являются необходимым условиями достижения минимума функцией &amp;lt;math&amp;gt; J &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; случайными значениями от 0 до 1;&lt;br /&gt;
# Вычислить центры кластеров &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; используя формулу &amp;lt;math&amp;gt;~(2)&amp;lt;/math&amp;gt;;&lt;br /&gt;
# Вычислить значение решающей функции по формуле &amp;lt;math&amp;gt;~(1)&amp;lt;/math&amp;gt;. Если значение &amp;lt;math&amp;gt; J &amp;lt; \varepsilon,~\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt; |J_{i} - J_{i-1}| &amp;lt; \delta,~\delta &amp;gt; 0 &amp;lt;/math&amp;gt;, то остановить вычисления;&lt;br /&gt;
# Иначе вычислить новые значения матрицы М по формуле &amp;lt;math&amp;gt;~(3)&amp;lt;/math&amp;gt;;&lt;br /&gt;
# Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительным ядром алгоритма являются формулы: &amp;lt;math&amp;gt; (1) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (2) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (3) &amp;lt;/math&amp;gt;. В них производится вычисление новых центров кластеров, значения решающей функции и пересчет элементов матрицы принадлежности.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Макроструктура алгоритма состоит из следующих шагов:&lt;br /&gt;
&lt;br /&gt;
# Инициализация матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; случайными значениями от 0 до 1;&lt;br /&gt;
# Вычисление центров кластеров; &lt;br /&gt;
# Вычисление значения решающей функции(если оно удовлетворяет условиям останова - завершение вычислений);&lt;br /&gt;
# Вычисление новых элементов матрицы принадлежности;&lt;br /&gt;
# Переход к шагу 2;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации алгоритма на языке С++&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    float ** m;&lt;br /&gt;
    int *c;&lt;br /&gt;
    int number_clusters, number_items;&lt;br /&gt;
    m = gen_random_clusters();//заполним матрицу m случайными значениями от 0 до 1&lt;br /&gt;
    &lt;br /&gt;
    while (true)&lt;br /&gt;
    {&lt;br /&gt;
      //вычисление центров кластеров&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
        {&lt;br /&gt;
            numerator==denumerator=0;&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
            {&lt;br /&gt;
                numerator+=pow(m[i, k], q)*u[k];//u[k]-вектор&lt;br /&gt;
                denumerator+=pow(m[i, k], q);&lt;br /&gt;
            }&lt;br /&gt;
        c[i]= numerator / denumerator;//центры кластеров&lt;br /&gt;
        }&lt;br /&gt;
    &lt;br /&gt;
        j=0;//вычисление решающей функции&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
                j+=pow(m[i, k], q)*pow(dist(c[i], x[k],2);//dist-вычисляет расстояние между заданными векторами&lt;br /&gt;
    &lt;br /&gt;
       if ((abs(j-last_j)&amp;lt;delta) || (j&amp;lt;eps)) break;//проверка на необходимость завернешения алгоритма&lt;br /&gt;
       last_j=j;&lt;br /&gt;
     //обновление матрицы m&lt;br /&gt;
       for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
          for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
             {&lt;br /&gt;
               m[i,k]=0&lt;br /&gt;
              for(int j=0; j&amp;lt;number_clusters; j++)&lt;br /&gt;
                  m[i,k]+=pow(dist(c[i], x[k])/dist(c[j], x[k]),2/(q-1));&lt;br /&gt;
              m[i,k]=1/m[i,k];&lt;br /&gt;
              }&lt;br /&gt;
                                       &lt;br /&gt;
    }&lt;br /&gt;
    &amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Каждая итерация включает в себя&lt;br /&gt;
* Вычисление центров кластеров &amp;lt;math&amp;gt;O(C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
* Вычисление решающей функции &amp;lt;math&amp;gt;O(C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
* Обновлене матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;O(C*C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
Общая сложность каждой итерации &amp;lt;math&amp;gt;O(C*C*K)&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;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; параллельных операций, каждая их которых в свою очередь состоит из &amp;lt;math&amp;gt;K&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;C*K&amp;lt;/math&amp;gt; параллельных операций.&lt;br /&gt;
Результатом его работы является значение решающей функции &amp;lt;math&amp;gt;J&amp;lt;/math&amp;gt;. Её значение определяет необходимость завершения алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Третий ярус&#039;&#039;&#039; включает &amp;lt;math&amp;gt;C*K&amp;lt;/math&amp;gt; параллельных операций, каждая из которых состоит из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; параллельных операций, и одной, которая выполняется с использованием результата предыдущих.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Снимок экрана 2016-10-15 в 23.10.05.png|582 px|thumb|center|Информационный граф]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
На каждом шаге алгоритма необходимо вычислять сумму элементов массивов. Сложность ее вычисления на первом шаге (вычисление центров кластеров) при параллельной реализации составляет &amp;lt;math&amp;gt;O(\log_{2} C)&amp;lt;/math&amp;gt;. Для каждого элемента из набора входных данных(&amp;lt;math&amp;gt; K &amp;lt;/math&amp;gt;), но здесь возможен независимый расчет(координатный параллелизм). На втором шаге(вычисление решающей функции) сложность будет &amp;lt;math&amp;gt;O(\log_{2} {C*K})&amp;lt;/math&amp;gt;, потому что здесь необходимо сложение всех элементов. На третьем шаге имеем сложность &amp;lt;math&amp;gt;O(\log_{2} C^2)&amp;lt;/math&amp;gt;. Итого суммарная сложность итерации: &amp;lt;math&amp;gt;O(\log_{2} {C*K} + \log_{2} C^3)&amp;lt;/math&amp;gt;. Воспользовавшись свойствами логарифма произведения получаем: &amp;lt;math&amp;gt;O(\log_{2} {K} + \log_{2} C^4)&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Скошенного параллелизма в алгоритме нет.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Входные данные:&lt;br /&gt;
* &amp;lt;math&amp;gt;u_{k} k = 1, ..., K&amp;lt;/math&amp;gt; - набор входных векторов;&lt;br /&gt;
* &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; - количество кластеров;&lt;br /&gt;
* &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость;&lt;br /&gt;
* &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0, ~\delta &amp;gt; 0&amp;lt;/math&amp;gt; - коэффициенты, описывающие точность алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные:&lt;br /&gt;
* &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; - матрица принадлежности.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
*Соотношение последовательной и параллельной сложности алгоритма: &amp;lt;math&amp;gt;C*C*K \over {\log_{2} {K} + \log_{2} C^4}&amp;lt;/math&amp;gt;. Соответственно при распараллеливании наибольший прирост в производительности мы получим при разбиении большого набора данных на большее число кластеров;&lt;br /&gt;
*Вычислительная мощность: &amp;lt;math&amp;gt;{{C^2*K} \over {C*K}} = C&amp;lt;/math&amp;gt;. Получается, что на чем большее количество кластеров мы разбиваем набор данных, тем менее затратным становится перемещение данных;&lt;br /&gt;
*Алгоритм не является устойчивым, как и другие подобные алгоритмы этого класса(например k-means). Очень многое зависит как от входных данных, так и от изначальных параметров приближения(заполнения матрицы принадлежности =&amp;gt; исходных центров кластеров);&lt;br /&gt;
*Не является детерминированным. Так же очень многое зависит как от входных данных, так и от изначальных параметров приближения(заполнения матрицы принадлежности =&amp;gt; исходных центров кластеров);&lt;br /&gt;
*Алгоритм не сбалансирован - доминирует операция умножения. Параллельные ветви алгоритма сбалансированы;&lt;br /&gt;
*Степень исхода вершины информационного графа - 2.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Можно найти следующие реализации алгоритма&lt;br /&gt;
* Для MATLAB http://www.mathworks.com/help/fuzzy/fcm.html &lt;br /&gt;
* В PostgreSQL http://num-meth.srcc.msu.ru/zhurnal/tom_2012/v13r207.html&lt;br /&gt;
Так же готовые реализации алгоритма и его описание можно найти на сайтах&lt;br /&gt;
* https://habrahabr.ru/post/208496/&lt;br /&gt;
* http://pythonhosted.org/scikit-fuzzy/auto_examples/plot_cmeans.html&lt;br /&gt;
* http://www.codeproject.com/Articles/91675/Computer-Vision-Applications-with-C-Fuzzy-C-means&lt;br /&gt;
* https://github.com/gyaikhom/fcm&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>ADovganich</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=12124</id>
		<title>Участник:ADovganich/Нечеткий алгоритм С средних</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=12124"/>
		<updated>2016-10-15T21:14:02Z</updated>

		<summary type="html">&lt;p&gt;ADovganich: &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(C*C*K*I)&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;K&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;C*K&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;3I&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;C*C*K&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Protsenko|Мария Проценко]] (1.5-1.8, 2.7), [[Участник:ADovganich|Андрей Довганич]] (1.1-1.4, 1.9, 1.10)&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Нечеткий алгоритм C-средних (fuzzy C-means) позволяет разбить имеющееся множество векторов (точек) мощностью K на заданное число нечетких множеств. Предназначен для кластеризации больших наборов данных. Основным достоинством алгоритма является нечеткость при определении объекта в кластер. Благодаря этому становится возможным определить объекты, которые находятся на границе, в кластеры. Из основного достоинства следует и главный недостаток - неопределенность с объектами, удаленными от центров всех кластеров. В остальном ему присущи стандартные проблемы подобного класса алгоритмов: вычислительная сложность, необходимость задания количества кластеров&amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм был разработан J.C. Dunn в 1973 г.&amp;lt;ref&amp;gt; Dunn, J. C. (1973-01-01). &amp;quot;A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters&amp;quot;. Journal of Cybernetics. 3 (3): 32–57. doi:10.1080/01969727308546046. ISSN 0022-0280.&amp;lt;/ref&amp;gt;, усовершенствован J.C. Bezdek в 1981 г.&amp;lt;ref&amp;gt; Bezdek, James C. (1981). Pattern Recognition with Fuzzy Objective Function Algorithms. ISBN 0-306-40671-3.&amp;lt;/ref&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;
# Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим матрицу &amp;lt;math&amp;gt; M = m_{ik} \in[0,1],\;  i = 1, ..., c, \; k = 1, ..., K &amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;m_{i,k}&amp;lt;/math&amp;gt; - вероятность принадлежности объекта &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; - количество векторов. При этом элементы матрицы удовлетворяют следующим условиям:&lt;br /&gt;
&lt;br /&gt;
* сумма элементов в каждом столбце равна &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* сумма всех элементов матрицы равно &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Назовем &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; матрицей принадлежности.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; - центры кластеров. Тогда рассмотрим функцию &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
J(M, c_{1}, c_{2},...c_{c}) = \sum_{i = 1}^{c}{J_{i}} = \sum_{i = 1}^{c}\sum_{k = 1}^{K}{m_{ik}^q}d_{ik}^2 ~(1)&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt; d_{ik} = \left\Vert{u_{k}-c_{i}}\right\| &amp;lt;/math&amp;gt; - Евклидово расстояние между центром кластера и объектом, &amp;lt;math&amp;gt; 1 \le q \le \infty &amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость. Будем минимизировать значение функции &amp;lt;math&amp;gt; J &amp;lt;/math&amp;gt;. Для этого вычислим центры кластеров по формуле &amp;lt;math&amp;gt; ~(2) &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c_{i} = {{\sum_{k = 1}^{K}{m_{ik}^q} * u_{k}} \over {\sum_{k = 1}^{K}{m_{ik}^q}}}~(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;m_{ik}&amp;lt;/math&amp;gt; — коэффициент принадлежности &amp;lt;math&amp;gt;u_{k}&amp;lt;/math&amp;gt; вектора к кластеру &amp;lt;math&amp;gt;c_{i}&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
и новые значения матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; по формуле &amp;lt;math&amp;gt; ~(3) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;m_{ik} = {1 \over \sum_{j = 1}^{c}{({{d_{ik}} \over {d_{jk}}})}^{2 \over q-1}} ~(3)&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; ~(2) &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; ~(3) &amp;lt;/math&amp;gt;являются необходимым условиями достижения минимума функцией &amp;lt;math&amp;gt; J &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; случайными значениями от 0 до 1;&lt;br /&gt;
# Вычислить центры кластеров &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; используя формулу &amp;lt;math&amp;gt;~(2)&amp;lt;/math&amp;gt;;&lt;br /&gt;
# Вычислить значение решающей функции по формуле &amp;lt;math&amp;gt;~(1)&amp;lt;/math&amp;gt;. Если значение &amp;lt;math&amp;gt; J &amp;lt; \varepsilon,~\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt; |J_{i} - J_{i-1}| &amp;lt; \delta,~\delta &amp;gt; 0 &amp;lt;/math&amp;gt;, то остановить вычисления;&lt;br /&gt;
# Иначе вычислить новые значения матрицы М по формуле &amp;lt;math&amp;gt;~(3)&amp;lt;/math&amp;gt;;&lt;br /&gt;
# Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительным ядром алгоритма являются формулы: &amp;lt;math&amp;gt; (1) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (2) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (3) &amp;lt;/math&amp;gt;. В них производится вычисление новых центров кластеров, значения решающей функции и пересчет элементов матрицы принадлежности.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Макроструктура алгоритма состоит из следующих шагов:&lt;br /&gt;
&lt;br /&gt;
# Инициализация матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; случайными значениями от 0 до 1;&lt;br /&gt;
# Вычисление центров кластеров; &lt;br /&gt;
# Вычисление значения решающей функции(если оно удовлетворяет условиям останова - завершение вычислений);&lt;br /&gt;
# Вычисление новых элементов матрицы принадлежности;&lt;br /&gt;
# Переход к шагу 2;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации алгоритма на языке С++&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    float ** m;&lt;br /&gt;
    int *c;&lt;br /&gt;
    int number_clusters, number_items;&lt;br /&gt;
    m = gen_random_clusters();//заполним матрицу m случайными значениями от 0 до 1&lt;br /&gt;
    &lt;br /&gt;
    while (true)&lt;br /&gt;
    {&lt;br /&gt;
      //вычисление центров кластеров&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
        {&lt;br /&gt;
            numerator==denumerator=0;&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
            {&lt;br /&gt;
                numerator+=pow(m[i, k], q)*u[k];//u[k]-вектор&lt;br /&gt;
                denumerator+=pow(m[i, k], q);&lt;br /&gt;
            }&lt;br /&gt;
        c[i]= numerator / denumerator;//центры кластеров&lt;br /&gt;
        }&lt;br /&gt;
    &lt;br /&gt;
        j=0;//вычисление решающей функции&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
                j+=pow(m[i, k], q)*pow(dist(c[i], x[k],2);//dist-вычисляет расстояние между заданными векторами&lt;br /&gt;
    &lt;br /&gt;
       if ((abs(j-last_j)&amp;lt;delta) || (j&amp;lt;eps)) break;//проверка на необходимость завернешения алгоритма&lt;br /&gt;
       last_j=j;&lt;br /&gt;
     //обновление матрицы m&lt;br /&gt;
       for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
          for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
             {&lt;br /&gt;
               m[i,k]=0&lt;br /&gt;
              for(int j=0; j&amp;lt;number_clusters; j++)&lt;br /&gt;
                  m[i,k]+=pow(dist(c[i], x[k])/dist(c[j], x[k]),2/(q-1));&lt;br /&gt;
              m[i,k]=1/m[i,k];&lt;br /&gt;
              }&lt;br /&gt;
                                       &lt;br /&gt;
    }&lt;br /&gt;
    &amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Каждая итерация включает в себя&lt;br /&gt;
* Вычисление центров кластеров &amp;lt;math&amp;gt;O(C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
* Вычисление решающей функции &amp;lt;math&amp;gt;O(C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
* Обновлене матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;O(C*C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
Общая сложность каждой итерации &amp;lt;math&amp;gt;O(C*C*K)&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;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; параллельных операций, каждая их которых в свою очередь состоит из &amp;lt;math&amp;gt;K&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;C*K&amp;lt;/math&amp;gt; параллельных операций.&lt;br /&gt;
Результатом его работы является значение решающей функции &amp;lt;math&amp;gt;J&amp;lt;/math&amp;gt;. Её значение определяет необходимость завершения алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Третий ярус&#039;&#039;&#039; включает &amp;lt;math&amp;gt;C*K&amp;lt;/math&amp;gt; параллельных операций, каждая из которых состоит из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; параллельных операций, и одной, которая выполняется с использованием результата предыдущих.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Снимок экрана 2016-10-15 в 23.10.05.png|582 px|thumb|center|Информационный граф]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
На каждом шаге алгоритма необходимо вычислять сумму элементов массивов. Сложность ее вычисления на первом шаге (вычисление центров кластеров) при параллельной реализации составляет &amp;lt;math&amp;gt;O(\log_{2} C)&amp;lt;/math&amp;gt;. Для каждого элемента из набора входных данных(&amp;lt;math&amp;gt; K &amp;lt;/math&amp;gt;), но здесь возможен независимый расчет(координатный параллелизм). На втором шаге(вычисление решающей функции) сложность будет &amp;lt;math&amp;gt;O(\log_{2} {C*K})&amp;lt;/math&amp;gt;, потому что здесь необходимо сложение всех элементов. На третьем шаге имеем сложность &amp;lt;math&amp;gt;O(\log_{2} C^2)&amp;lt;/math&amp;gt;. Итого суммарная сложность итерации: &amp;lt;math&amp;gt;O(\log_{2} {C*K} + \log_{2} C^3)&amp;lt;/math&amp;gt;. Воспользовавшись свойствами логарифма произведения получаем: &amp;lt;math&amp;gt;O(\log_{2} {K} + \log_{2} C^4)&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Скошенного параллелизма в алгоритме нет.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Входные данные:&lt;br /&gt;
* &amp;lt;math&amp;gt;u_{k} k = 1, ..., K&amp;lt;/math&amp;gt; - набор входных векторов;&lt;br /&gt;
* &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; - количество кластеров;&lt;br /&gt;
* &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость;&lt;br /&gt;
* &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0, ~\delta &amp;gt; 0&amp;lt;/math&amp;gt; - коэффициенты, описывающие точность алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные:&lt;br /&gt;
* &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; - матрица принадлежности.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
*Соотношение последовательной и параллельной сложности алгоритма: &amp;lt;math&amp;gt;C*C*K \over {\log_{2} {K} + \log_{2} C^4}&amp;lt;/math&amp;gt;. Соответственно при распараллеливании наибольший прирост в производительности мы получим при разбиении большого набора данных на большее число кластеров;&lt;br /&gt;
*Вычислительная мощность: &amp;lt;math&amp;gt;{{C^2*K} \over {C*K}} = C&amp;lt;/math&amp;gt;. Получается, что на чем большее количество кластеров мы разбиваем набор данных, тем менее затратным становится перемещение данных;&lt;br /&gt;
*Алгоритм не является устойчивым, как и другие подобные алгоритмы этого класса(например k-means). Очень многое зависит как от входных данных, так и от изначальных параметров приближения(заполнения матрицы принадлежности =&amp;gt; исходных центров кластеров);&lt;br /&gt;
*Не является детерминированным. Так же очень многое зависит как от входных данных, так и от изначальных параметров приближения(заполнения матрицы принадлежности =&amp;gt; исходных центров кластеров);&lt;br /&gt;
*Алгоритм не сбалансирован - доминирует операция умножения. Параллельные ветви алгоритма сбалансированы;&lt;br /&gt;
*Степень исхода вершины информационного графа - 2.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Можно найти следующие реализации алгоритма&lt;br /&gt;
* Для MATLAB http://www.mathworks.com/help/fuzzy/fcm.html &lt;br /&gt;
* В PostgreSQL http://num-meth.srcc.msu.ru/zhurnal/tom_2012/v13r207.html&lt;br /&gt;
Так же готовые реализации алгоритма и его описание можно найти на сайтах&lt;br /&gt;
* https://habrahabr.ru/post/208496/&lt;br /&gt;
* http://pythonhosted.org/scikit-fuzzy/auto_examples/plot_cmeans.html&lt;br /&gt;
* http://www.codeproject.com/Articles/91675/Computer-Vision-Applications-with-C-Fuzzy-C-means&lt;br /&gt;
* https://github.com/gyaikhom/fcm&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>ADovganich</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=12123</id>
		<title>Участник:ADovganich/Нечеткий алгоритм С средних</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=12123"/>
		<updated>2016-10-15T21:13:47Z</updated>

		<summary type="html">&lt;p&gt;ADovganich: &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(C*C*K*I)&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;K&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data          = &amp;lt;math&amp;gt;C*K&amp;lt;/math&amp;gt;, [матрица принадлежности]&lt;br /&gt;
| pf_height        = &amp;lt;math&amp;gt;3I&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width       = &amp;lt;math&amp;gt;C*C*K&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Protsenko|Мария Проценко]] (1.5-1.8, 2.7), [[Участник:ADovganich|Андрей Довганич]] (1.1-1.4, 1.9, 1.10)&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Нечеткий алгоритм C-средних (fuzzy C-means) позволяет разбить имеющееся множество векторов (точек) мощностью K на заданное число нечетких множеств. Предназначен для кластеризации больших наборов данных. Основным достоинством алгоритма является нечеткость при определении объекта в кластер. Благодаря этому становится возможным определить объекты, которые находятся на границе, в кластеры. Из основного достоинства следует и главный недостаток - неопределенность с объектами, удаленными от центров всех кластеров. В остальном ему присущи стандартные проблемы подобного класса алгоритмов: вычислительная сложность, необходимость задания количества кластеров&amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм был разработан J.C. Dunn в 1973 г.&amp;lt;ref&amp;gt; Dunn, J. C. (1973-01-01). &amp;quot;A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters&amp;quot;. Journal of Cybernetics. 3 (3): 32–57. doi:10.1080/01969727308546046. ISSN 0022-0280.&amp;lt;/ref&amp;gt;, усовершенствован J.C. Bezdek в 1981 г.&amp;lt;ref&amp;gt; Bezdek, James C. (1981). Pattern Recognition with Fuzzy Objective Function Algorithms. ISBN 0-306-40671-3.&amp;lt;/ref&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;
# Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим матрицу &amp;lt;math&amp;gt; M = m_{ik} \in[0,1],\;  i = 1, ..., c, \; k = 1, ..., K &amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;m_{i,k}&amp;lt;/math&amp;gt; - вероятность принадлежности объекта &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; - количество векторов. При этом элементы матрицы удовлетворяют следующим условиям:&lt;br /&gt;
&lt;br /&gt;
* сумма элементов в каждом столбце равна &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* сумма всех элементов матрицы равно &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Назовем &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; матрицей принадлежности.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; - центры кластеров. Тогда рассмотрим функцию &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
J(M, c_{1}, c_{2},...c_{c}) = \sum_{i = 1}^{c}{J_{i}} = \sum_{i = 1}^{c}\sum_{k = 1}^{K}{m_{ik}^q}d_{ik}^2 ~(1)&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt; d_{ik} = \left\Vert{u_{k}-c_{i}}\right\| &amp;lt;/math&amp;gt; - Евклидово расстояние между центром кластера и объектом, &amp;lt;math&amp;gt; 1 \le q \le \infty &amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость. Будем минимизировать значение функции &amp;lt;math&amp;gt; J &amp;lt;/math&amp;gt;. Для этого вычислим центры кластеров по формуле &amp;lt;math&amp;gt; ~(2) &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c_{i} = {{\sum_{k = 1}^{K}{m_{ik}^q} * u_{k}} \over {\sum_{k = 1}^{K}{m_{ik}^q}}}~(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;m_{ik}&amp;lt;/math&amp;gt; — коэффициент принадлежности &amp;lt;math&amp;gt;u_{k}&amp;lt;/math&amp;gt; вектора к кластеру &amp;lt;math&amp;gt;c_{i}&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
и новые значения матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; по формуле &amp;lt;math&amp;gt; ~(3) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;m_{ik} = {1 \over \sum_{j = 1}^{c}{({{d_{ik}} \over {d_{jk}}})}^{2 \over q-1}} ~(3)&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; ~(2) &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; ~(3) &amp;lt;/math&amp;gt;являются необходимым условиями достижения минимума функцией &amp;lt;math&amp;gt; J &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; случайными значениями от 0 до 1;&lt;br /&gt;
# Вычислить центры кластеров &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; используя формулу &amp;lt;math&amp;gt;~(2)&amp;lt;/math&amp;gt;;&lt;br /&gt;
# Вычислить значение решающей функции по формуле &amp;lt;math&amp;gt;~(1)&amp;lt;/math&amp;gt;. Если значение &amp;lt;math&amp;gt; J &amp;lt; \varepsilon,~\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt; |J_{i} - J_{i-1}| &amp;lt; \delta,~\delta &amp;gt; 0 &amp;lt;/math&amp;gt;, то остановить вычисления;&lt;br /&gt;
# Иначе вычислить новые значения матрицы М по формуле &amp;lt;math&amp;gt;~(3)&amp;lt;/math&amp;gt;;&lt;br /&gt;
# Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительным ядром алгоритма являются формулы: &amp;lt;math&amp;gt; (1) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (2) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (3) &amp;lt;/math&amp;gt;. В них производится вычисление новых центров кластеров, значения решающей функции и пересчет элементов матрицы принадлежности.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Макроструктура алгоритма состоит из следующих шагов:&lt;br /&gt;
&lt;br /&gt;
# Инициализация матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; случайными значениями от 0 до 1;&lt;br /&gt;
# Вычисление центров кластеров; &lt;br /&gt;
# Вычисление значения решающей функции(если оно удовлетворяет условиям останова - завершение вычислений);&lt;br /&gt;
# Вычисление новых элементов матрицы принадлежности;&lt;br /&gt;
# Переход к шагу 2;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации алгоритма на языке С++&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    float ** m;&lt;br /&gt;
    int *c;&lt;br /&gt;
    int number_clusters, number_items;&lt;br /&gt;
    m = gen_random_clusters();//заполним матрицу m случайными значениями от 0 до 1&lt;br /&gt;
    &lt;br /&gt;
    while (true)&lt;br /&gt;
    {&lt;br /&gt;
      //вычисление центров кластеров&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
        {&lt;br /&gt;
            numerator==denumerator=0;&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
            {&lt;br /&gt;
                numerator+=pow(m[i, k], q)*u[k];//u[k]-вектор&lt;br /&gt;
                denumerator+=pow(m[i, k], q);&lt;br /&gt;
            }&lt;br /&gt;
        c[i]= numerator / denumerator;//центры кластеров&lt;br /&gt;
        }&lt;br /&gt;
    &lt;br /&gt;
        j=0;//вычисление решающей функции&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
                j+=pow(m[i, k], q)*pow(dist(c[i], x[k],2);//dist-вычисляет расстояние между заданными векторами&lt;br /&gt;
    &lt;br /&gt;
       if ((abs(j-last_j)&amp;lt;delta) || (j&amp;lt;eps)) break;//проверка на необходимость завернешения алгоритма&lt;br /&gt;
       last_j=j;&lt;br /&gt;
     //обновление матрицы m&lt;br /&gt;
       for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
          for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
             {&lt;br /&gt;
               m[i,k]=0&lt;br /&gt;
              for(int j=0; j&amp;lt;number_clusters; j++)&lt;br /&gt;
                  m[i,k]+=pow(dist(c[i], x[k])/dist(c[j], x[k]),2/(q-1));&lt;br /&gt;
              m[i,k]=1/m[i,k];&lt;br /&gt;
              }&lt;br /&gt;
                                       &lt;br /&gt;
    }&lt;br /&gt;
    &amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Каждая итерация включает в себя&lt;br /&gt;
* Вычисление центров кластеров &amp;lt;math&amp;gt;O(C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
* Вычисление решающей функции &amp;lt;math&amp;gt;O(C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
* Обновлене матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;O(C*C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
Общая сложность каждой итерации &amp;lt;math&amp;gt;O(C*C*K)&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;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; параллельных операций, каждая их которых в свою очередь состоит из &amp;lt;math&amp;gt;K&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;C*K&amp;lt;/math&amp;gt; параллельных операций.&lt;br /&gt;
Результатом его работы является значение решающей функции &amp;lt;math&amp;gt;J&amp;lt;/math&amp;gt;. Её значение определяет необходимость завершения алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Третий ярус&#039;&#039;&#039; включает &amp;lt;math&amp;gt;C*K&amp;lt;/math&amp;gt; параллельных операций, каждая из которых состоит из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; параллельных операций, и одной, которая выполняется с использованием результата предыдущих.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Снимок экрана 2016-10-15 в 23.10.05.png|582 px|thumb|center|Информационный граф]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
На каждом шаге алгоритма необходимо вычислять сумму элементов массивов. Сложность ее вычисления на первом шаге (вычисление центров кластеров) при параллельной реализации составляет &amp;lt;math&amp;gt;O(\log_{2} C)&amp;lt;/math&amp;gt;. Для каждого элемента из набора входных данных(&amp;lt;math&amp;gt; K &amp;lt;/math&amp;gt;), но здесь возможен независимый расчет(координатный параллелизм). На втором шаге(вычисление решающей функции) сложность будет &amp;lt;math&amp;gt;O(\log_{2} {C*K})&amp;lt;/math&amp;gt;, потому что здесь необходимо сложение всех элементов. На третьем шаге имеем сложность &amp;lt;math&amp;gt;O(\log_{2} C^2)&amp;lt;/math&amp;gt;. Итого суммарная сложность итерации: &amp;lt;math&amp;gt;O(\log_{2} {C*K} + \log_{2} C^3)&amp;lt;/math&amp;gt;. Воспользовавшись свойствами логарифма произведения получаем: &amp;lt;math&amp;gt;O(\log_{2} {K} + \log_{2} C^4)&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Скошенного параллелизма в алгоритме нет.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Входные данные:&lt;br /&gt;
* &amp;lt;math&amp;gt;u_{k} k = 1, ..., K&amp;lt;/math&amp;gt; - набор входных векторов;&lt;br /&gt;
* &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; - количество кластеров;&lt;br /&gt;
* &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость;&lt;br /&gt;
* &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0, ~\delta &amp;gt; 0&amp;lt;/math&amp;gt; - коэффициенты, описывающие точность алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные:&lt;br /&gt;
* &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; - матрица принадлежности.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
*Соотношение последовательной и параллельной сложности алгоритма: &amp;lt;math&amp;gt;C*C*K \over {\log_{2} {K} + \log_{2} C^4}&amp;lt;/math&amp;gt;. Соответственно при распараллеливании наибольший прирост в производительности мы получим при разбиении большого набора данных на большее число кластеров;&lt;br /&gt;
*Вычислительная мощность: &amp;lt;math&amp;gt;{{C^2*K} \over {C*K}} = C&amp;lt;/math&amp;gt;. Получается, что на чем большее количество кластеров мы разбиваем набор данных, тем менее затратным становится перемещение данных;&lt;br /&gt;
*Алгоритм не является устойчивым, как и другие подобные алгоритмы этого класса(например k-means). Очень многое зависит как от входных данных, так и от изначальных параметров приближения(заполнения матрицы принадлежности =&amp;gt; исходных центров кластеров);&lt;br /&gt;
*Не является детерминированным. Так же очень многое зависит как от входных данных, так и от изначальных параметров приближения(заполнения матрицы принадлежности =&amp;gt; исходных центров кластеров);&lt;br /&gt;
*Алгоритм не сбалансирован - доминирует операция умножения. Параллельные ветви алгоритма сбалансированы;&lt;br /&gt;
*Степень исхода вершины информационного графа - 2.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Можно найти следующие реализации алгоритма&lt;br /&gt;
* Для MATLAB http://www.mathworks.com/help/fuzzy/fcm.html &lt;br /&gt;
* В PostgreSQL http://num-meth.srcc.msu.ru/zhurnal/tom_2012/v13r207.html&lt;br /&gt;
Так же готовые реализации алгоритма и его описание можно найти на сайтах&lt;br /&gt;
* https://habrahabr.ru/post/208496/&lt;br /&gt;
* http://pythonhosted.org/scikit-fuzzy/auto_examples/plot_cmeans.html&lt;br /&gt;
* http://www.codeproject.com/Articles/91675/Computer-Vision-Applications-with-C-Fuzzy-C-means&lt;br /&gt;
* https://github.com/gyaikhom/fcm&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>ADovganich</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=12088</id>
		<title>Участник:ADovganich/Нечеткий алгоритм С средних</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=12088"/>
		<updated>2016-10-15T21:04:16Z</updated>

		<summary type="html">&lt;p&gt;ADovganich: /* Ресурс параллелизма алгоритма */&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 = &lt;br /&gt;
| input_data         = &lt;br /&gt;
| output_data          = &lt;br /&gt;
| pf_height        = &lt;br /&gt;
| pf_width       = &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Protsenko|Мария Проценко]] (1.5-1.8, 2.7), [[Участник:ADovganich|Андрей Довганич]] (1.1-1.4, 1.9, 1.10)&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Нечеткий алгоритм C-средних (fuzzy C-means) позволяет разбить имеющееся множество векторов (точек) мощностью K на заданное число нечетких множеств. Предназначен для кластеризации больших наборов данных. Основным достоинством алгоритма является нечеткость при определении объекта в кластер. Благодаря этому становится возможным определить объекты, которые находятся на границе, в кластеры. Из основного достоинства следует и главный недостаток - неопределенность с объектами, удаленными от центров всех кластеров. В остальном ему присущи стандартные проблемы подобного класса алгоритмов: вычислительная сложность, необходимость задания количества кластеров&amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм был разработан J.C. Dunn в 1973 г.&amp;lt;ref&amp;gt; Dunn, J. C. (1973-01-01). &amp;quot;A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters&amp;quot;. Journal of Cybernetics. 3 (3): 32–57. doi:10.1080/01969727308546046. ISSN 0022-0280.&amp;lt;/ref&amp;gt;, усовершенствован J.C. Bezdek в 1981 г.&amp;lt;ref&amp;gt; Bezdek, James C. (1981). Pattern Recognition with Fuzzy Objective Function Algorithms. ISBN 0-306-40671-3.&amp;lt;/ref&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;
# Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим матрицу &amp;lt;math&amp;gt; M = m_{ik} \in[0,1],\;  i = 1, ..., c, \; k = 1, ..., K &amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;m_{i,k}&amp;lt;/math&amp;gt; - вероятность принадлежности объекта &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; - количество векторов. При этом элементы матрицы удовлетворяют следующим условиям:&lt;br /&gt;
&lt;br /&gt;
* сумма элементов в каждом столбце равна &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* сумма всех элементов матрицы равно &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Назовем &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; матрицей принадлежности.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; - центры кластеров. Тогда рассмотрим функцию &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
J(M, c_{1}, c_{2},...c_{c}) = \sum_{i = 1}^{c}{J_{i}} = \sum_{i = 1}^{c}\sum_{k = 1}^{K}{m_{ik}^q}d_{ik}^2 ~(1)&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt; d_{ik} = \left\Vert{u_{k}-c_{i}}\right\| &amp;lt;/math&amp;gt; - Евклидово расстояние между центром кластера и объектом, &amp;lt;math&amp;gt; 1 \le q \le \infty &amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость. Будем минимизировать значение функции &amp;lt;math&amp;gt; J &amp;lt;/math&amp;gt;. Для этого вычислим центры кластеров по формуле &amp;lt;math&amp;gt; ~(2) &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c_{i} = {{\sum_{k = 1}^{K}{m_{ik}^q} * u_{k}} \over {\sum_{k = 1}^{K}{m_{ik}^q}}}~(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;m_{ik}&amp;lt;/math&amp;gt; — коэффициент принадлежности &amp;lt;math&amp;gt;u_{k}&amp;lt;/math&amp;gt; вектора к кластеру &amp;lt;math&amp;gt;c_{i}&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
и новые значения матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; по формуле &amp;lt;math&amp;gt; ~(3) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;m_{ik} = {1 \over \sum_{j = 1}^{c}{({{d_{ik}} \over {d_{jk}}})}^{2 \over q-1}} ~(3)&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; ~(2) &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; ~(3) &amp;lt;/math&amp;gt;являются необходимым условиями достижения минимума функцией &amp;lt;math&amp;gt; J &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; случайными значениями от 0 до 1;&lt;br /&gt;
# Вычислить центры кластеров &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; используя формулу &amp;lt;math&amp;gt;~(2)&amp;lt;/math&amp;gt;;&lt;br /&gt;
# Вычислить значение решающей функции по формуле &amp;lt;math&amp;gt;~(1)&amp;lt;/math&amp;gt;. Если значение &amp;lt;math&amp;gt; J &amp;lt; \varepsilon,~\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt; |J_{i} - J_{i-1}| &amp;lt; \delta,~\delta &amp;gt; 0 &amp;lt;/math&amp;gt;, то остановить вычисления;&lt;br /&gt;
# Иначе вычислить новые значения матрицы М по формуле &amp;lt;math&amp;gt;~(3)&amp;lt;/math&amp;gt;;&lt;br /&gt;
# Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительным ядром алгоритма являются формулы: &amp;lt;math&amp;gt; (1) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (2) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (3) &amp;lt;/math&amp;gt;. В них производится вычисление новых центров кластеров, значения решающей функции и пересчет элементов матрицы принадлежности.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Макроструктура алгоритма состоит из следующих шагов:&lt;br /&gt;
&lt;br /&gt;
# Инициализация матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; случайными значениями от 0 до 1;&lt;br /&gt;
# Вычисление центров кластеров; &lt;br /&gt;
# Вычисление значения решающей функции(если оно удовлетворяет условиям останова - завершение вычислений);&lt;br /&gt;
# Вычисление новых элементов матрицы принадлежности;&lt;br /&gt;
# Переход к шагу 2;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации алгоритма на языке С++&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    float ** m;&lt;br /&gt;
    int *c;&lt;br /&gt;
    int number_clusters, number_items;&lt;br /&gt;
    m = gen_random_clusters();//заполним матрицу m случайными значениями от 0 до 1&lt;br /&gt;
    &lt;br /&gt;
    while (true)&lt;br /&gt;
    {&lt;br /&gt;
      //вычисление центров кластеров&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
        {&lt;br /&gt;
            numerator==denumerator=0;&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
            {&lt;br /&gt;
                numerator+=pow(m[i, k], q)*u[k];//u[k]-вектор&lt;br /&gt;
                denumerator+=pow(m[i, k], q);&lt;br /&gt;
            }&lt;br /&gt;
        c[i]= numerator / denumerator;//центры кластеров&lt;br /&gt;
        }&lt;br /&gt;
    &lt;br /&gt;
        j=0;//вычисление решающей функции&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
                j+=pow(m[i, k], q)*pow(dist(c[i], x[k],2);//dist-вычисляет расстояние между заданными векторами&lt;br /&gt;
    &lt;br /&gt;
       if ((abs(j-last_j)&amp;lt;delta) || (j&amp;lt;eps)) break;//проверка на необходимость завернешения алгоритма&lt;br /&gt;
       last_j=j;&lt;br /&gt;
     //обновление матрицы m&lt;br /&gt;
       for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
          for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
             {&lt;br /&gt;
               m[i,k]=0&lt;br /&gt;
              for(int j=0; j&amp;lt;number_clusters; j++)&lt;br /&gt;
                  m[i,k]+=pow(dist(c[i], x[k])/dist(c[j], x[k]),2/(q-1));&lt;br /&gt;
              m[i,k]=1/m[i,k];&lt;br /&gt;
              }&lt;br /&gt;
                                       &lt;br /&gt;
    }&lt;br /&gt;
    &amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Каждая итерация включает в себя&lt;br /&gt;
* Вычисление центров кластеров &amp;lt;math&amp;gt;O(C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
* Вычисление решающей функции &amp;lt;math&amp;gt;O(C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
* Обновлене матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;O(C*C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
Общая сложность каждой итерации &amp;lt;math&amp;gt;O(C*C*K)&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;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; параллельных операций, каждая их которых в свою очередь состоит из &amp;lt;math&amp;gt;K&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;C*K&amp;lt;/math&amp;gt; параллельных операций.&lt;br /&gt;
Результатом его работы является значение решающей функции &amp;lt;math&amp;gt;J&amp;lt;/math&amp;gt;. Её значение определяет необходимость завершения алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Третий ярус&#039;&#039;&#039; включает &amp;lt;math&amp;gt;C*K&amp;lt;/math&amp;gt; параллельных операций, каждая из которых состоит из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; параллельных операций, и одной, которая выполняется с использованием результата предыдущих.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Снимок экрана 2016-10-15 в 23.10.05.png|582 px|thumb|center|Информационный граф]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
На каждом шаге алгоритма необходимо вычислять сумму элементов массивов. Сложность ее вычисления на первом шаге (вычисление центров кластеров) при параллельной реализации составляет &amp;lt;math&amp;gt;O(\log_{2} C)&amp;lt;/math&amp;gt;. Для каждого элемента из набора входных данных(&amp;lt;math&amp;gt; K &amp;lt;/math&amp;gt;), но здесь возможен независимый расчет(координатный параллелизм). На втором шаге(вычисление решающей функции) сложность будет &amp;lt;math&amp;gt;O(\log_{2} {C*K})&amp;lt;/math&amp;gt;, потому что здесь необходимо сложение всех элементов. На третьем шаге имеем сложность &amp;lt;math&amp;gt;O(\log_{2} C^2)&amp;lt;/math&amp;gt;. Итого суммарная сложность итерации: &amp;lt;math&amp;gt;O(\log_{2} {C*K} + \log_{2} C^3)&amp;lt;/math&amp;gt;. Воспользовавшись свойствами логарифма произведения получаем: &amp;lt;math&amp;gt;O(\log_{2} {K} + \log_{2} C^4)&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Скошенного параллелизма в алгоритме нет.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Входные данные:&lt;br /&gt;
* &amp;lt;math&amp;gt;u_{k} k = 1, ..., K&amp;lt;/math&amp;gt; - набор входных векторов;&lt;br /&gt;
* &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; - количество кластеров;&lt;br /&gt;
* &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость;&lt;br /&gt;
* &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0, ~\delta &amp;gt; 0&amp;lt;/math&amp;gt; - коэффициенты, описывающие точность алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные:&lt;br /&gt;
* &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; - матрица принадлежности.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
*Соотношение последовательной и параллельной сложности алгоритма: &amp;lt;math&amp;gt;C*C*K \over {\log_{2} {K} + \log_{2} C^4}&amp;lt;/math&amp;gt;. Соответственно при распараллеливании наибольший прирост в производительности мы получим при разбиении большого набора данных на большее число кластеров;&lt;br /&gt;
*Вычислительная мощность: &amp;lt;math&amp;gt;{{C^2*K} \over {C*K}} = C&amp;lt;/math&amp;gt;. Получается, что на чем большее количество кластеров мы разбиваем набор данных, тем менее затратным становится перемещение данных;&lt;br /&gt;
*Алгоритм не является устойчивым, как и другие подобные алгоритмы этого класса(например k-means). Очень многое зависит как от входных данных, так и от изначальных параметров приближения(заполнения матрицы принадлежности =&amp;gt; исходных центров кластеров);&lt;br /&gt;
*Не является детерминированным. Так же очень многое зависит как от входных данных, так и от изначальных параметров приближения(заполнения матрицы принадлежности =&amp;gt; исходных центров кластеров);&lt;br /&gt;
*Алгоритм не сбалансирован - доминирует операция умножения. Параллельные ветви алгоритма сбалансированы;&lt;br /&gt;
*Степень исхода вершины информационного графа - 2.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Можно найти следующие реализации алгоритма&lt;br /&gt;
* Для MATLAB http://www.mathworks.com/help/fuzzy/fcm.html &lt;br /&gt;
* В PostgreSQL http://num-meth.srcc.msu.ru/zhurnal/tom_2012/v13r207.html&lt;br /&gt;
Так же готовые реализации алгоритма и его описание можно найти на сайтах&lt;br /&gt;
* https://habrahabr.ru/post/208496/&lt;br /&gt;
* http://pythonhosted.org/scikit-fuzzy/auto_examples/plot_cmeans.html&lt;br /&gt;
* http://www.codeproject.com/Articles/91675/Computer-Vision-Applications-with-C-Fuzzy-C-means&lt;br /&gt;
* https://github.com/gyaikhom/fcm&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>ADovganich</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=11999</id>
		<title>Участник:ADovganich/Нечеткий алгоритм С средних</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=11999"/>
		<updated>2016-10-15T20:52:54Z</updated>

		<summary type="html">&lt;p&gt;ADovganich: /* Информационный граф */&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 = &lt;br /&gt;
| input_data         = &lt;br /&gt;
| output_data          = &lt;br /&gt;
| pf_height        = &lt;br /&gt;
| pf_width       = &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Protsenko|Мария Проценко]] (1.5-1.8, 2.7), [[Участник:ADovganich|Андрей Довганич]] (1.1-1.4, 1.9, 1.10)&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Нечеткий алгоритм C-средних (fuzzy C-means) позволяет разбить имеющееся множество векторов (точек) мощностью K на заданное число нечетких множеств. Предназначен для кластеризации больших наборов данных. Основным достоинством алгоритма является нечеткость при определении объекта в кластер. Благодаря этому становится возможным определить объекты, которые находятся на границе, в кластеры. Из основного достоинства следует и главный недостаток - неопределенность с объектами, удаленными от центров всех кластеров. В остальном ему присущи стандартные проблемы подобного класса алгоритмов: вычислительная сложность, необходимость задания количества кластеров&amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм был разработан J.C. Dunn в 1973 г.&amp;lt;ref&amp;gt; Dunn, J. C. (1973-01-01). &amp;quot;A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters&amp;quot;. Journal of Cybernetics. 3 (3): 32–57. doi:10.1080/01969727308546046. ISSN 0022-0280.&amp;lt;/ref&amp;gt;, усовершенствован J.C. Bezdek в 1981 г.&amp;lt;ref&amp;gt; Bezdek, James C. (1981). Pattern Recognition with Fuzzy Objective Function Algorithms. ISBN 0-306-40671-3.&amp;lt;/ref&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;
# Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим матрицу &amp;lt;math&amp;gt; M = m_{ik} \in[0,1],\;  i = 1, ..., c, \; k = 1, ..., K &amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;m_{i,k}&amp;lt;/math&amp;gt; - вероятность принадлежности объекта &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; - количество векторов. При этом элементы матрицы удовлетворяют следующим условиям:&lt;br /&gt;
&lt;br /&gt;
* сумма элементов в каждом столбце равна &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* сумма всех элементов матрицы равно &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Назовем &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; матрицей принадлежности.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; - центры кластеров. Тогда рассмотрим функцию &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
J(M, c_{1}, c_{2},...c_{c}) = \sum_{i = 1}^{c}{J_{i}} = \sum_{i = 1}^{c}\sum_{k = 1}^{K}{m_{ik}^q}d_{ik}^2 ~(1)&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt; d_{ik} = \left\Vert{u_{k}-c_{i}}\right\| &amp;lt;/math&amp;gt; - Евклидово расстояние между центром кластера и объектом, &amp;lt;math&amp;gt; 1 \le q \le \infty &amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость. Будем минимизировать значение функции &amp;lt;math&amp;gt; J &amp;lt;/math&amp;gt;. Для этого вычислим центры кластеров по формуле &amp;lt;math&amp;gt; ~(2) &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c_{i} = {{\sum_{k = 1}^{K}{m_{ik}^q} * u_{k}} \over {\sum_{k = 1}^{K}{m_{ik}^q}}}~(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;m_{ik}&amp;lt;/math&amp;gt; — коэффициент принадлежности &amp;lt;math&amp;gt;u_{k}&amp;lt;/math&amp;gt; вектора к кластеру &amp;lt;math&amp;gt;c_{i}&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
и новые значения матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; по формуле &amp;lt;math&amp;gt; ~(3) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;m_{ik} = {1 \over \sum_{j = 1}^{c}{({{d_{ik}} \over {d_{jk}}})}^{2 \over q-1}} ~(3)&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; ~(2) &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; ~(3) &amp;lt;/math&amp;gt;являются необходимым условиями достижения минимума функцией &amp;lt;math&amp;gt; J &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; случайными значениями от 0 до 1;&lt;br /&gt;
# Вычислить центры кластеров &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; используя формулу &amp;lt;math&amp;gt;~(2)&amp;lt;/math&amp;gt;;&lt;br /&gt;
# Вычислить значение решающей функции по формуле &amp;lt;math&amp;gt;~(1)&amp;lt;/math&amp;gt;. Если значение &amp;lt;math&amp;gt; J &amp;lt; \varepsilon,~\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt; |J_{i} - J_{i-1}| &amp;lt; \delta,~\delta &amp;gt; 0 &amp;lt;/math&amp;gt;, то остановить вычисления;&lt;br /&gt;
# Иначе вычислить новые значения матрицы М по формуле &amp;lt;math&amp;gt;~(3)&amp;lt;/math&amp;gt;;&lt;br /&gt;
# Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительным ядром алгоритма являются формулы: &amp;lt;math&amp;gt; (1) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (2) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (3) &amp;lt;/math&amp;gt;. В них производится вычисление новых центров кластеров, значения решающей функции и пересчет элементов матрицы принадлежности.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Макроструктура алгоритма состоит из следующих шагов:&lt;br /&gt;
&lt;br /&gt;
# Инициализация матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; случайными значениями от 0 до 1;&lt;br /&gt;
# Вычисление центров кластеров; &lt;br /&gt;
# Вычисление значения решающей функции(если оно удовлетворяет условиям останова - завершение вычислений);&lt;br /&gt;
# Вычисление новых элементов матрицы принадлежности;&lt;br /&gt;
# Переход к шагу 2;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации алгоритма на языке С++&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    float ** m;&lt;br /&gt;
    int *c;&lt;br /&gt;
    int number_clusters, number_items;&lt;br /&gt;
    m = gen_random_clusters();//заполним матрицу m случайными значениями от 0 до 1&lt;br /&gt;
    &lt;br /&gt;
    while (true)&lt;br /&gt;
    {&lt;br /&gt;
      //вычисление центров кластеров&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
        {&lt;br /&gt;
            numerator==denumerator=0;&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
            {&lt;br /&gt;
                numerator+=pow(m[i, k], q)*u[k];//u[k]-вектор&lt;br /&gt;
                denumerator+=pow(m[i, k], q);&lt;br /&gt;
            }&lt;br /&gt;
        c[i]= numerator / denumerator;//центры кластеров&lt;br /&gt;
        }&lt;br /&gt;
    &lt;br /&gt;
        j=0;//вычисление решающей функции&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
                j+=pow(m[i, k], q)*pow(dist(c[i], x[k],2);//dist-вычисляет расстояние между заданными векторами&lt;br /&gt;
    &lt;br /&gt;
       if ((abs(j-last_j)&amp;lt;delta) || (j&amp;lt;eps)) break;//проверка на необходимость завернешения алгоритма&lt;br /&gt;
       last_j=j;&lt;br /&gt;
     //обновление матрицы m&lt;br /&gt;
       for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
          for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
             {&lt;br /&gt;
               m[i,k]=0&lt;br /&gt;
              for(int j=0; j&amp;lt;number_clusters; j++)&lt;br /&gt;
                  m[i,k]+=pow(dist(c[i], x[k])/dist(c[j], x[k]),2/(q-1));&lt;br /&gt;
              m[i,k]=1/m[i,k];&lt;br /&gt;
              }&lt;br /&gt;
                                       &lt;br /&gt;
    }&lt;br /&gt;
    &amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Каждая итерация включает в себя&lt;br /&gt;
* Вычисление центров кластеров &amp;lt;math&amp;gt;O(C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
* Вычисление решающей функции &amp;lt;math&amp;gt;O(C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
* Обновлене матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;O(C*C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
Общая сложность каждой итерации &amp;lt;math&amp;gt;O(C*C*K)&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;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; параллельных операций, каждая их которых в свою очередь состоит из &amp;lt;math&amp;gt;K&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;C*K&amp;lt;/math&amp;gt; параллельных операций.&lt;br /&gt;
Результатом его работы является значение решающей функции &amp;lt;math&amp;gt;J&amp;lt;/math&amp;gt;. Её значение определяет необходимость завершения алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Третий ярус&#039;&#039;&#039; включает &amp;lt;math&amp;gt;C*K&amp;lt;/math&amp;gt; параллельных операций, каждая из которых состоит из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; параллельных операций, и одной, которая выполняется с использованием результата предыдущих.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Снимок экрана 2016-10-15 в 23.10.05.png|582 px|thumb|center|Информационный граф]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
На каждом шаге алгоритма необходимо вычислять сумму элементов массива. Её вычисление на первом шаге(вычисление центров кластеров) будет занимать при параллельной реализации &amp;lt;math&amp;gt;O(\log_{2} C)&amp;lt;/math&amp;gt;. Для каждого элемента из набора входных данных(&amp;lt;math&amp;gt; K &amp;lt;/math&amp;gt;), но здесь возможен независимый расчет(координатный параллелизм). На втором шаге(вычисление решающей функции) - &amp;lt;math&amp;gt;O(\log_{2} {C*K})&amp;lt;/math&amp;gt;, потому что здесь необходимо сложение всех элементов. На третьем шаге имеем сложность &amp;lt;math&amp;gt;O(\log_{2} C^2)&amp;lt;/math&amp;gt;. Итого суммарная сложность итерации: &amp;lt;math&amp;gt;O(\log_{2} {C*K} + \log_{2} C^3)&amp;lt;/math&amp;gt;. Воспользовавшись свойствами логарифма произведения получаем: &amp;lt;math&amp;gt;O(\log_{2} {K} + \log_{2} C^4)&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Скошенного параллелизма в алгоритме нет.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Входные данные:&lt;br /&gt;
* &amp;lt;math&amp;gt;u_{k} k = 1, ..., K&amp;lt;/math&amp;gt; - набор входных векторов;&lt;br /&gt;
* &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; - количество кластеров;&lt;br /&gt;
* &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость;&lt;br /&gt;
* &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0, ~\delta &amp;gt; 0&amp;lt;/math&amp;gt; - коэффициенты, описывающие точность алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные:&lt;br /&gt;
* &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; - матрица принадлежности.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
*Соотношение последовательной и параллельной сложности алгоритма: &amp;lt;math&amp;gt;C*C*K \over {\log_{2} {K} + \log_{2} C^4}&amp;lt;/math&amp;gt;. Соответственно при распараллеливании наибольший прирост в производительности мы получим при разбиении большого набора данных на большее число кластеров;&lt;br /&gt;
*Вычислительная мощность: &amp;lt;math&amp;gt;{{C^2*K} \over {C*K}} = C&amp;lt;/math&amp;gt;. Получается, что на чем большее количество кластеров мы разбиваем набор данных, тем менее затратным становится перемещение данных;&lt;br /&gt;
*Алгоритм не является устойчивым, как и другие подобные алгоритмы этого класса(например k-means). Очень многое зависит как от входных данных, так и от изначальных параметров приближения(заполнения матрицы принадлежности =&amp;gt; исходных центров кластеров);&lt;br /&gt;
*Не является детерминированным. Так же очень многое зависит как от входных данных, так и от изначальных параметров приближения(заполнения матрицы принадлежности =&amp;gt; исходных центров кластеров);&lt;br /&gt;
*Алгоритм не сбалансирован - доминирует операция умножения. Параллельные ветви алгоритма сбалансированы;&lt;br /&gt;
*Степень исхода вершины информационного графа - 2.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Можно найти следующие реализации алгоритма&lt;br /&gt;
* Для MATLAB http://www.mathworks.com/help/fuzzy/fcm.html &lt;br /&gt;
* В PostgreSQL http://num-meth.srcc.msu.ru/zhurnal/tom_2012/v13r207.html&lt;br /&gt;
Так же готовые реализации алгоритма и его описание можно найти на сайтах&lt;br /&gt;
* https://habrahabr.ru/post/208496/&lt;br /&gt;
* http://pythonhosted.org/scikit-fuzzy/auto_examples/plot_cmeans.html&lt;br /&gt;
* http://www.codeproject.com/Articles/91675/Computer-Vision-Applications-with-C-Fuzzy-C-means&lt;br /&gt;
* https://github.com/gyaikhom/fcm&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>ADovganich</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=11945</id>
		<title>Участник:ADovganich/Нечеткий алгоритм С средних</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=11945"/>
		<updated>2016-10-15T20:47:09Z</updated>

		<summary type="html">&lt;p&gt;ADovganich: &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 = &lt;br /&gt;
| input_data         = &lt;br /&gt;
| output_data          = &lt;br /&gt;
| pf_height        = &lt;br /&gt;
| pf_width       = &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Protsenko|Мария Проценко]] (1.5-1.8, 2.7), [[Участник:ADovganich|Андрей Довганич]] (1.1-1.4, 1.9, 1.10)&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Нечеткий алгоритм C-средних (fuzzy C-means) позволяет разбить имеющееся множество векторов (точек) мощностью K на заданное число нечетких множеств. Предназначен для кластеризации больших наборов данных. Основным достоинством алгоритма является нечеткость при определении объекта в кластер. Благодаря этому становится возможным определить объекты, которые находятся на границе, в кластеры. Из основного достоинства следует и главный недостаток - неопределенность с объектами, удаленными от центров всех кластеров. В остальном ему присущи стандартные проблемы подобного класса алгоритмов: вычислительная сложность, необходимость задания количества кластеров&amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм был разработан J.C. Dunn в 1973 г.&amp;lt;ref&amp;gt; Dunn, J. C. (1973-01-01). &amp;quot;A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters&amp;quot;. Journal of Cybernetics. 3 (3): 32–57. doi:10.1080/01969727308546046. ISSN 0022-0280.&amp;lt;/ref&amp;gt;, усовершенствован J.C. Bezdek в 1981 г.&amp;lt;ref&amp;gt; Bezdek, James C. (1981). Pattern Recognition with Fuzzy Objective Function Algorithms. ISBN 0-306-40671-3.&amp;lt;/ref&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;
# Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим матрицу &amp;lt;math&amp;gt; M = m_{ik} \in[0,1],\;  i = 1, ..., c, \; k = 1, ..., K &amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;m_{i,k}&amp;lt;/math&amp;gt; - вероятность принадлежности объекта &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; - количество векторов. При этом элементы матрицы удовлетворяют следующим условиям:&lt;br /&gt;
&lt;br /&gt;
* сумма элементов в каждом столбце равна &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* сумма всех элементов матрицы равно &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Назовем &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; матрицей принадлежности.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; - центры кластеров. Тогда рассмотрим функцию &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
J(M, c_{1}, c_{2},...c_{c}) = \sum_{i = 1}^{c}{J_{i}} = \sum_{i = 1}^{c}\sum_{k = 1}^{K}{m_{ik}^q}d_{ik}^2 ~(1)&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt; d_{ik} = \left\Vert{u_{k}-c_{i}}\right\| &amp;lt;/math&amp;gt; - Евклидово расстояние между центром кластера и объектом, &amp;lt;math&amp;gt; 1 \le q \le \infty &amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость. Будем минимизировать значение функции &amp;lt;math&amp;gt; J &amp;lt;/math&amp;gt;. Для этого вычислим центры кластеров по формуле &amp;lt;math&amp;gt; ~(2) &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c_{i} = {{\sum_{k = 1}^{K}{m_{ik}^q} * u_{k}} \over {\sum_{k = 1}^{K}{m_{ik}^q}}}~(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;m_{ik}&amp;lt;/math&amp;gt; — коэффициент принадлежности &amp;lt;math&amp;gt;u_{k}&amp;lt;/math&amp;gt; вектора к кластеру &amp;lt;math&amp;gt;c_{i}&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
и новые значения матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; по формуле &amp;lt;math&amp;gt; ~(3) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;m_{ik} = {1 \over \sum_{j = 1}^{c}{({{d_{ik}} \over {d_{jk}}})}^{2 \over q-1}} ~(3)&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; ~(2) &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; ~(3) &amp;lt;/math&amp;gt;являются необходимым условиями достижения минимума функцией &amp;lt;math&amp;gt; J &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; случайными значениями от 0 до 1;&lt;br /&gt;
# Вычислить центры кластеров &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; используя формулу &amp;lt;math&amp;gt;~(2)&amp;lt;/math&amp;gt;;&lt;br /&gt;
# Вычислить значение решающей функции по формуле &amp;lt;math&amp;gt;~(1)&amp;lt;/math&amp;gt;. Если значение &amp;lt;math&amp;gt; J &amp;lt; \varepsilon,~\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt; |J_{i} - J_{i-1}| &amp;lt; \delta,~\delta &amp;gt; 0 &amp;lt;/math&amp;gt;, то остановить вычисления;&lt;br /&gt;
# Иначе вычислить новые значения матрицы М по формуле &amp;lt;math&amp;gt;~(3)&amp;lt;/math&amp;gt;;&lt;br /&gt;
# Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительным ядром алгоритма являются формулы: &amp;lt;math&amp;gt; (1) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (2) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (3) &amp;lt;/math&amp;gt;. В них производится вычисление новых центров кластеров, значения решающей функции и пересчет элементов матрицы принадлежности.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Макроструктура алгоритма состоит из следующих шагов:&lt;br /&gt;
&lt;br /&gt;
# Инициализация матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; случайными значениями от 0 до 1;&lt;br /&gt;
# Вычисление центров кластеров; &lt;br /&gt;
# Вычисление значения решающей функции(если оно удовлетворяет условиям останова - завершение вычислений);&lt;br /&gt;
# Вычисление новых элементов матрицы принадлежности;&lt;br /&gt;
# Переход к шагу 2;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации алгоритма на языке С++&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    float ** m;&lt;br /&gt;
    int *c;&lt;br /&gt;
    int number_clusters, number_items;&lt;br /&gt;
    m = gen_random_clusters();//заполним матрицу m случайными значениями от 0 до 1&lt;br /&gt;
    &lt;br /&gt;
    while (true)&lt;br /&gt;
    {&lt;br /&gt;
      //вычисление центров кластеров&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
        {&lt;br /&gt;
            numerator==denumerator=0;&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
            {&lt;br /&gt;
                numerator+=pow(m[i, k], q)*u[k];//u[k]-вектор&lt;br /&gt;
                denumerator+=pow(m[i, k], q);&lt;br /&gt;
            }&lt;br /&gt;
        c[i]= numerator / denumerator;//центры кластеров&lt;br /&gt;
        }&lt;br /&gt;
    &lt;br /&gt;
        j=0;//вычисление решающей функции&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
                j+=pow(m[i, k], q)*pow(dist(c[i], x[k],2);//dist-вычисляет расстояние между заданными векторами&lt;br /&gt;
    &lt;br /&gt;
       if ((abs(j-last_j)&amp;lt;delta) || (j&amp;lt;eps)) break;//проверка на необходимость завернешения алгоритма&lt;br /&gt;
       last_j=j;&lt;br /&gt;
     //обновление матрицы m&lt;br /&gt;
       for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
          for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
             {&lt;br /&gt;
               m[i,k]=0&lt;br /&gt;
              for(int j=0; j&amp;lt;number_clusters; j++)&lt;br /&gt;
                  m[i,k]+=pow(dist(c[i], x[k])/dist(c[j], x[k]),2/(q-1));&lt;br /&gt;
              m[i,k]=1/m[i,k];&lt;br /&gt;
              }&lt;br /&gt;
                                       &lt;br /&gt;
    }&lt;br /&gt;
    &amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Каждая итерация включает в себя&lt;br /&gt;
* Вычисление центров кластеров &amp;lt;math&amp;gt;O(C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
* Вычисление решающей функции &amp;lt;math&amp;gt;O(C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
* Обновлене матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;O(C*C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
Общая сложность каждой итерации &amp;lt;math&amp;gt;O(C*C*K)&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;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; параллельных операций, каждая их которых в свою очередь состоит из &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; параллельных операций, и одной, которая выполняется с использованием результата предыдущих.&lt;br /&gt;
Результатом работы этого яруса является значение &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; , которое будет использоваться на следующем ярусе.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй ярус&#039;&#039;&#039; содержит в себе &amp;lt;math&amp;gt;C*K&amp;lt;/math&amp;gt; параллельных операций.&lt;br /&gt;
Результатом его работы является значение решающей функции &amp;lt;math&amp;gt;J&amp;lt;/math&amp;gt;, значение которой влияет на необходимость завершения алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Третий ярус&#039;&#039;&#039; включает &amp;lt;math&amp;gt;C*K&amp;lt;/math&amp;gt; параллельных операций, каждая из которых состоит из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; параллельных операций, и одной, которая выполняется с использованием результата предыдущих.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Снимок экрана 2016-10-15 в 23.10.05.png|582 px|thumb|center|Информационный граф]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
На каждом шаге алгоритма необходимо вычислять сумму элементов массива. Её вычисление на первом шаге(вычисление центров кластеров) будет занимать при параллельной реализации &amp;lt;math&amp;gt;O(\log_{2} C)&amp;lt;/math&amp;gt;. Для каждого элемента из набора входных данных(&amp;lt;math&amp;gt; K &amp;lt;/math&amp;gt;), но здесь возможен независимый расчет(координатный параллелизм). На втором шаге(вычисление решающей функции) - &amp;lt;math&amp;gt;O(\log_{2} {C*K})&amp;lt;/math&amp;gt;, потому что здесь необходимо сложение всех элементов. На третьем шаге имеем сложность &amp;lt;math&amp;gt;O(\log_{2} C^2)&amp;lt;/math&amp;gt;. Итого суммарная сложность итерации: &amp;lt;math&amp;gt;O(\log_{2} {C*K} + \log_{2} C^3)&amp;lt;/math&amp;gt;. Воспользовавшись свойствами логарифма произведения получаем: &amp;lt;math&amp;gt;O(\log_{2} {K} + \log_{2} C^4)&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Скошенного параллелизма в алгоритме нет.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Входные данные:&lt;br /&gt;
* &amp;lt;math&amp;gt;u_{k} k = 1, ..., K&amp;lt;/math&amp;gt; - набор входных векторов;&lt;br /&gt;
* &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; - количество кластеров;&lt;br /&gt;
* &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость;&lt;br /&gt;
* &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0, ~\delta &amp;gt; 0&amp;lt;/math&amp;gt; - коэффициенты, описывающие точность алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные:&lt;br /&gt;
* &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; - матрица принадлежности.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
*Соотношение последовательной и параллельной сложности алгоритма: &amp;lt;math&amp;gt;C*C*K \over {\log_{2} {K} + \log_{2} C^4}&amp;lt;/math&amp;gt;. Соответственно при распараллеливании наибольший прирост в производительности мы получим при разбиении большого набора данных на большее число кластеров;&lt;br /&gt;
*Вычислительная мощность: &amp;lt;math&amp;gt;{{C^2*K} \over {C*K}} = C&amp;lt;/math&amp;gt;. Получается, что на чем большее количество кластеров мы разбиваем набор данных, тем менее затратным становится перемещение данных;&lt;br /&gt;
*Алгоритм не является устойчивым, как и другие подобные алгоритмы этого класса(например k-means). Очень многое зависит как от входных данных, так и от изначальных параметров приближения(заполнения матрицы принадлежности =&amp;gt; исходных центров кластеров);&lt;br /&gt;
*Не является детерминированным. Так же очень многое зависит как от входных данных, так и от изначальных параметров приближения(заполнения матрицы принадлежности =&amp;gt; исходных центров кластеров);&lt;br /&gt;
*Алгоритм не сбалансирован - доминирует операция умножения. Параллельные ветви алгоритма сбалансированы;&lt;br /&gt;
*Степень исхода вершины информационного графа - 2.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Можно найти следующие реализации алгоритма&lt;br /&gt;
* Для MATLAB http://www.mathworks.com/help/fuzzy/fcm.html &lt;br /&gt;
* В PostgreSQL http://num-meth.srcc.msu.ru/zhurnal/tom_2012/v13r207.html&lt;br /&gt;
Так же готовые реализации алгоритма и его описание можно найти на сайтах&lt;br /&gt;
* https://habrahabr.ru/post/208496/&lt;br /&gt;
* http://pythonhosted.org/scikit-fuzzy/auto_examples/plot_cmeans.html&lt;br /&gt;
* http://www.codeproject.com/Articles/91675/Computer-Vision-Applications-with-C-Fuzzy-C-means&lt;br /&gt;
* https://github.com/gyaikhom/fcm&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>ADovganich</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=11908</id>
		<title>Участник:ADovganich/Нечеткий алгоритм С средних</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=11908"/>
		<updated>2016-10-15T20:43:20Z</updated>

		<summary type="html">&lt;p&gt;ADovganich: /* Ресурс параллелизма алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &lt;br /&gt;
| input_data         = &lt;br /&gt;
| output_data          = &lt;br /&gt;
| pf_height        = &lt;br /&gt;
| pf_width       = &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Protsenko|Мария Проценко]] (1.5-1.8, 1.10, 2.7), [[Участник:ADovganich|Андрей Довганич]] (1.1-1.4, 1.9)&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Нечеткий алгоритм C-средних (fuzzy C-means) позволяет разбить имеющееся множество векторов (точек) мощностью p на заданное число нечетких множеств. Предназначен для кластеризации больших наборов данных. Основным достоинством алгоритма является нечеткость при определении объекта в кластер. Благодаря этому становится возможным определить объекты, которые находятся на границе, в кластеры. Из основного достоинства следует и главный недостаток - неопределенность с объектами, удаленными от центров всех кластеров. В остальном ему присущи стандартные проблемы подобного класса алгоритмов: вычислительная сложность, необходимость задания количества кластеров&amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм был разработан J.C. Dunn в 1973 г.&amp;lt;ref&amp;gt; Dunn, J. C. (1973-01-01). &amp;quot;A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters&amp;quot;. Journal of Cybernetics. 3 (3): 32–57. doi:10.1080/01969727308546046. ISSN 0022-0280.&amp;lt;/ref&amp;gt;, усовершенствован J.C. Bezdek в 1981 г.&amp;lt;ref&amp;gt; Bezdek, James C. (1981). Pattern Recognition with Fuzzy Objective Function Algorithms. ISBN 0-306-40671-3.&amp;lt;/ref&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;
# Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим матрицу &amp;lt;math&amp;gt; M = m_{ik} \in[0,1],\;  i = 1, ..., c, \; k = 1, ..., K &amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;m_{i,k}&amp;lt;/math&amp;gt; - вероятность принадлежности объекта &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; - количество векторов. При этом элементы матрицы удовлетворяют следующим условиям:&lt;br /&gt;
&lt;br /&gt;
* сумма элементов в каждом столбце равна &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* сумма всех элементов матрицы равно &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Назовем &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; матрицей принадлежности.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; - центры кластеров. Тогда рассмотрим функцию &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
J(M, c_{1}, c_{2},...c_{c}) = \sum_{i = 1}^{c}{J_{i}} = \sum_{i = 1}^{c}\sum_{k = 1}^{K}{m_{ik}^q}d_{ik}^2 ~(1)&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt; d_{ik} = \left\Vert{u_{k}-c_{i}}\right\| &amp;lt;/math&amp;gt; - Евклидово расстояние между центром кластера и объектом, &amp;lt;math&amp;gt; 1 \le q \le \infty &amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость. Будем минимизировать значение функции &amp;lt;math&amp;gt; J &amp;lt;/math&amp;gt;. Для этого вычислим центры кластеров по формуле &amp;lt;math&amp;gt; ~(2) &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c_{i} = {{\sum_{k = 1}^{K}{m_{ik}^q} * u_{k}} \over {\sum_{k = 1}^{K}{m_{ik}^q}}}~(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;m_{ik}&amp;lt;/math&amp;gt; — коэффициент принадлежности &amp;lt;math&amp;gt;u_{k}&amp;lt;/math&amp;gt; вектора к кластеру &amp;lt;math&amp;gt;c_{i}&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
и новые значения матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; по формуле &amp;lt;math&amp;gt; ~(3) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;m_{ik} = {1 \over \sum_{j = 1}^{c}{({{d_{ik}} \over {d_{jk}}})}^{2 \over q-1}} ~(3)&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; ~(2) &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; ~(3) &amp;lt;/math&amp;gt;являются необходимым условиями достижения минимума функцией &amp;lt;math&amp;gt; J &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; случайными значениями от 0 до 1;&lt;br /&gt;
# Вычислить центры кластеров &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; используя формулу &amp;lt;math&amp;gt;~(2)&amp;lt;/math&amp;gt;;&lt;br /&gt;
# Вычислить значение решающей функции по формуле &amp;lt;math&amp;gt;~(1)&amp;lt;/math&amp;gt;. Если значение &amp;lt;math&amp;gt; J &amp;lt; \varepsilon,~\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt; |J_{i} - J_{i-1}| &amp;lt; \delta,~\delta &amp;gt; 0 &amp;lt;/math&amp;gt;, то остановить вычисления;&lt;br /&gt;
# Иначе вычислить новые значения матрицы М по формуле &amp;lt;math&amp;gt;~(3)&amp;lt;/math&amp;gt;;&lt;br /&gt;
# Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительным ядром алгоритма являются формулы: &amp;lt;math&amp;gt; (1) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (2) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (3) &amp;lt;/math&amp;gt;. В них производится вычисление новых центров кластеров, значения решающей функции и пересчет элементов матрицы принадлежности.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Макроструктура алгоритма состоит из следующих шагов:&lt;br /&gt;
&lt;br /&gt;
1) Инициализация матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; случайными значениями от 0 до 1;&lt;br /&gt;
&lt;br /&gt;
2) Вычисление центров кластеров; &lt;br /&gt;
&lt;br /&gt;
3) Вычисление значения решающей функции(если оно удовлетворяет условиям останова - завершение вычислений);&lt;br /&gt;
&lt;br /&gt;
4) Вычисление новых элементов матрицы принадлежности;&lt;br /&gt;
&lt;br /&gt;
5) Переход к шагу 2;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации алгоритма на языке С++&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    float ** m;&lt;br /&gt;
    int *c;&lt;br /&gt;
    int number_clusters, number_items;&lt;br /&gt;
    m = gen_random_clusters();//заполним матрицу m случайными значениями от 0 до 1&lt;br /&gt;
    &lt;br /&gt;
    while (true)&lt;br /&gt;
    {&lt;br /&gt;
      //вычисление центров кластеров&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
        {&lt;br /&gt;
            numerator==denumerator=0;&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
            {&lt;br /&gt;
                numerator+=pow(m[i, k], q)*u[k];//u[k]-вектор&lt;br /&gt;
                denumerator+=pow(m[i, k], q);&lt;br /&gt;
            }&lt;br /&gt;
        c[i]= numerator / denumerator;//центры кластеров&lt;br /&gt;
        }&lt;br /&gt;
    &lt;br /&gt;
        j=0;//вычисление решающей функции&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
                j+=pow(m[i, k], q)*pow(dist(c[i], x[k],2);//dist-вычисляет расстояние между заданными векторами&lt;br /&gt;
    &lt;br /&gt;
       if ((abs(j-last_j)&amp;lt;delta) || (j&amp;lt;eps)) break;//проверка на необходимость завернешения алгоритма&lt;br /&gt;
       last_j=j;&lt;br /&gt;
     //обновление матрицы m&lt;br /&gt;
       for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
          for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
             {&lt;br /&gt;
               m[i,k]=0&lt;br /&gt;
              for(int j=0; j&amp;lt;number_clusters; j++)&lt;br /&gt;
                  m[i,k]+=pow(dist(c[i], x[k])/dist(c[j], x[k]),2/(q-1));&lt;br /&gt;
              m[i,k]=1/m[i,k];&lt;br /&gt;
              }&lt;br /&gt;
                                       &lt;br /&gt;
    }&lt;br /&gt;
    &amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Каждая итерация включает в себя&lt;br /&gt;
* Вычисление центров кластеров &amp;lt;math&amp;gt;O(C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
* Вычисление решающей функции &amp;lt;math&amp;gt;O(C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
* Обновлене матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;O(C*C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
Общая сложность каждой итерации &amp;lt;math&amp;gt;O(C*C*K)&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;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; параллельных операций, каждая их которых в свою очередь состоит из &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; параллельных операций, и одной, которая выполняется с использованием результата предыдущих.&lt;br /&gt;
Результатом работы этого яруса является значение &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; , которое будет использоваться на следующем ярусе.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй ярус&#039;&#039;&#039; содержит в себе &amp;lt;math&amp;gt;C*K&amp;lt;/math&amp;gt; параллельных операций.&lt;br /&gt;
Результатом его работы является значение решающей функции &amp;lt;math&amp;gt;J&amp;lt;/math&amp;gt;, значение которой влияет на необходимость завершения алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Третий ярус&#039;&#039;&#039; включает &amp;lt;math&amp;gt;C*K&amp;lt;/math&amp;gt; параллельных операций, каждая из которых состоит из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; параллельных операций, и одной, которая выполняется с использованием результата предыдущих.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Снимок экрана 2016-10-15 в 23.10.05.png|582 px|thumb|center|Информационный граф]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
На каждом шаге алгоритма необходимо вычислять сумму элементов массива. Её вычисление на первом шаге(вычисление центров кластеров) будет занимать при параллельной реализации &amp;lt;math&amp;gt;O(\log_{2} C)&amp;lt;/math&amp;gt;. Для каждого элемента из набора входных данных(&amp;lt;math&amp;gt; K &amp;lt;/math&amp;gt;), но здесь возможен независимый расчет(координатный параллелизм). На втором шаге(вычисление решающей функции) - &amp;lt;math&amp;gt;O(\log_{2} {C*K})&amp;lt;/math&amp;gt;, потому что здесь необходимо сложение всех элементов. На третьем шаге имеем сложность &amp;lt;math&amp;gt;O(\log_{2} C^2)&amp;lt;/math&amp;gt;. Итого суммарная сложность итерации: &amp;lt;math&amp;gt;O(\log_{2} {C*K} + \log_{2} C^3)&amp;lt;/math&amp;gt;. Воспользовавшись свойствами логарифма произведения получаем: &amp;lt;math&amp;gt;O(\log_{2} {K} + \log_{2} C^4)&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Скошенного параллелизма в алгоритме нет.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Входные данные:&lt;br /&gt;
* &amp;lt;math&amp;gt;u_{k} k = 1, ..., K&amp;lt;/math&amp;gt; - набор входных векторов;&lt;br /&gt;
* &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; - количество кластеров;&lt;br /&gt;
* &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость;&lt;br /&gt;
* &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0, ~\delta &amp;gt; 0&amp;lt;/math&amp;gt; - коэффициенты, описывающие точность алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные:&lt;br /&gt;
* &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; - матрица принадлежности.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
*Соотношение последовательной и параллельной сложности алгоритма: &amp;lt;math&amp;gt;C*C*K \over {\log_{2} {K} + \log_{2} C^4}&amp;lt;/math&amp;gt;. Соответственно при распараллеливании наибольший прирост в производительности мы получим при разбиении большого набора данных на большее число кластеров;&lt;br /&gt;
*Вычислительная мощность: &amp;lt;math&amp;gt;{{C^2*K} \over {C*K}} = C&amp;lt;/math&amp;gt;. Получается, что на чем большее количество кластеров мы разбиваем набор данных, тем менее затратным становится перемещение данных;&lt;br /&gt;
*Алгоритм не является устойчивым, как и другие подобные алгоритмы этого класса(например k-means). Очень многое зависит как от входных данных, так и от изначальных параметров приближения(заполнения матрицы принадлежности =&amp;gt; исходных центров кластеров);&lt;br /&gt;
*Не является детерминированным. Так же очень многое зависит как от входных данных, так и от изначальных параметров приближения(заполнения матрицы принадлежности =&amp;gt; исходных центров кластеров);&lt;br /&gt;
*Алгоритм не сбалансирован - доминирует операция умножения. Параллельные ветви алгоритма сбалансированы;&lt;br /&gt;
*Степень исхода вершины информационного графа - 2.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Можно найти следующие реализации алгоритма&lt;br /&gt;
* Для MATLAB http://www.mathworks.com/help/fuzzy/fcm.html &lt;br /&gt;
* В PostgreSQL http://num-meth.srcc.msu.ru/zhurnal/tom_2012/v13r207.html&lt;br /&gt;
Так же готовые реализации алгоритма и его описание можно найти на сайтах&lt;br /&gt;
* https://habrahabr.ru/post/208496/&lt;br /&gt;
* http://pythonhosted.org/scikit-fuzzy/auto_examples/plot_cmeans.html&lt;br /&gt;
* http://www.codeproject.com/Articles/91675/Computer-Vision-Applications-with-C-Fuzzy-C-means&lt;br /&gt;
* https://github.com/gyaikhom/fcm&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>ADovganich</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=11906</id>
		<title>Участник:ADovganich/Нечеткий алгоритм С средних</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=11906"/>
		<updated>2016-10-15T20:43:15Z</updated>

		<summary type="html">&lt;p&gt;ADovganich: /* Свойства алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &lt;br /&gt;
| input_data         = &lt;br /&gt;
| output_data          = &lt;br /&gt;
| pf_height        = &lt;br /&gt;
| pf_width       = &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Protsenko|Мария Проценко]] (1.5-1.8, 1.10, 2.7), [[Участник:ADovganich|Андрей Довганич]] (1.1-1.4, 1.9)&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Нечеткий алгоритм C-средних (fuzzy C-means) позволяет разбить имеющееся множество векторов (точек) мощностью p на заданное число нечетких множеств. Предназначен для кластеризации больших наборов данных. Основным достоинством алгоритма является нечеткость при определении объекта в кластер. Благодаря этому становится возможным определить объекты, которые находятся на границе, в кластеры. Из основного достоинства следует и главный недостаток - неопределенность с объектами, удаленными от центров всех кластеров. В остальном ему присущи стандартные проблемы подобного класса алгоритмов: вычислительная сложность, необходимость задания количества кластеров&amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм был разработан J.C. Dunn в 1973 г.&amp;lt;ref&amp;gt; Dunn, J. C. (1973-01-01). &amp;quot;A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters&amp;quot;. Journal of Cybernetics. 3 (3): 32–57. doi:10.1080/01969727308546046. ISSN 0022-0280.&amp;lt;/ref&amp;gt;, усовершенствован J.C. Bezdek в 1981 г.&amp;lt;ref&amp;gt; Bezdek, James C. (1981). Pattern Recognition with Fuzzy Objective Function Algorithms. ISBN 0-306-40671-3.&amp;lt;/ref&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;
# Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим матрицу &amp;lt;math&amp;gt; M = m_{ik} \in[0,1],\;  i = 1, ..., c, \; k = 1, ..., K &amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;m_{i,k}&amp;lt;/math&amp;gt; - вероятность принадлежности объекта &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; - количество векторов. При этом элементы матрицы удовлетворяют следующим условиям:&lt;br /&gt;
&lt;br /&gt;
* сумма элементов в каждом столбце равна &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* сумма всех элементов матрицы равно &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Назовем &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; матрицей принадлежности.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; - центры кластеров. Тогда рассмотрим функцию &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
J(M, c_{1}, c_{2},...c_{c}) = \sum_{i = 1}^{c}{J_{i}} = \sum_{i = 1}^{c}\sum_{k = 1}^{K}{m_{ik}^q}d_{ik}^2 ~(1)&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt; d_{ik} = \left\Vert{u_{k}-c_{i}}\right\| &amp;lt;/math&amp;gt; - Евклидово расстояние между центром кластера и объектом, &amp;lt;math&amp;gt; 1 \le q \le \infty &amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость. Будем минимизировать значение функции &amp;lt;math&amp;gt; J &amp;lt;/math&amp;gt;. Для этого вычислим центры кластеров по формуле &amp;lt;math&amp;gt; ~(2) &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c_{i} = {{\sum_{k = 1}^{K}{m_{ik}^q} * u_{k}} \over {\sum_{k = 1}^{K}{m_{ik}^q}}}~(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;m_{ik}&amp;lt;/math&amp;gt; — коэффициент принадлежности &amp;lt;math&amp;gt;u_{k}&amp;lt;/math&amp;gt; вектора к кластеру &amp;lt;math&amp;gt;c_{i}&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
и новые значения матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; по формуле &amp;lt;math&amp;gt; ~(3) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;m_{ik} = {1 \over \sum_{j = 1}^{c}{({{d_{ik}} \over {d_{jk}}})}^{2 \over q-1}} ~(3)&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; ~(2) &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; ~(3) &amp;lt;/math&amp;gt;являются необходимым условиями достижения минимума функцией &amp;lt;math&amp;gt; J &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; случайными значениями от 0 до 1;&lt;br /&gt;
# Вычислить центры кластеров &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; используя формулу &amp;lt;math&amp;gt;~(2)&amp;lt;/math&amp;gt;;&lt;br /&gt;
# Вычислить значение решающей функции по формуле &amp;lt;math&amp;gt;~(1)&amp;lt;/math&amp;gt;. Если значение &amp;lt;math&amp;gt; J &amp;lt; \varepsilon,~\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt; |J_{i} - J_{i-1}| &amp;lt; \delta,~\delta &amp;gt; 0 &amp;lt;/math&amp;gt;, то остановить вычисления;&lt;br /&gt;
# Иначе вычислить новые значения матрицы М по формуле &amp;lt;math&amp;gt;~(3)&amp;lt;/math&amp;gt;;&lt;br /&gt;
# Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительным ядром алгоритма являются формулы: &amp;lt;math&amp;gt; (1) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (2) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (3) &amp;lt;/math&amp;gt;. В них производится вычисление новых центров кластеров, значения решающей функции и пересчет элементов матрицы принадлежности.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Макроструктура алгоритма состоит из следующих шагов:&lt;br /&gt;
&lt;br /&gt;
1) Инициализация матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; случайными значениями от 0 до 1;&lt;br /&gt;
&lt;br /&gt;
2) Вычисление центров кластеров; &lt;br /&gt;
&lt;br /&gt;
3) Вычисление значения решающей функции(если оно удовлетворяет условиям останова - завершение вычислений);&lt;br /&gt;
&lt;br /&gt;
4) Вычисление новых элементов матрицы принадлежности;&lt;br /&gt;
&lt;br /&gt;
5) Переход к шагу 2;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации алгоритма на языке С++&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    float ** m;&lt;br /&gt;
    int *c;&lt;br /&gt;
    int number_clusters, number_items;&lt;br /&gt;
    m = gen_random_clusters();//заполним матрицу m случайными значениями от 0 до 1&lt;br /&gt;
    &lt;br /&gt;
    while (true)&lt;br /&gt;
    {&lt;br /&gt;
      //вычисление центров кластеров&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
        {&lt;br /&gt;
            numerator==denumerator=0;&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
            {&lt;br /&gt;
                numerator+=pow(m[i, k], q)*u[k];//u[k]-вектор&lt;br /&gt;
                denumerator+=pow(m[i, k], q);&lt;br /&gt;
            }&lt;br /&gt;
        c[i]= numerator / denumerator;//центры кластеров&lt;br /&gt;
        }&lt;br /&gt;
    &lt;br /&gt;
        j=0;//вычисление решающей функции&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
                j+=pow(m[i, k], q)*pow(dist(c[i], x[k],2);//dist-вычисляет расстояние между заданными векторами&lt;br /&gt;
    &lt;br /&gt;
       if ((abs(j-last_j)&amp;lt;delta) || (j&amp;lt;eps)) break;//проверка на необходимость завернешения алгоритма&lt;br /&gt;
       last_j=j;&lt;br /&gt;
     //обновление матрицы m&lt;br /&gt;
       for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
          for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
             {&lt;br /&gt;
               m[i,k]=0&lt;br /&gt;
              for(int j=0; j&amp;lt;number_clusters; j++)&lt;br /&gt;
                  m[i,k]+=pow(dist(c[i], x[k])/dist(c[j], x[k]),2/(q-1));&lt;br /&gt;
              m[i,k]=1/m[i,k];&lt;br /&gt;
              }&lt;br /&gt;
                                       &lt;br /&gt;
    }&lt;br /&gt;
    &amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Каждая итерация включает в себя&lt;br /&gt;
* Вычисление центров кластеров &amp;lt;math&amp;gt;O(C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
* Вычисление решающей функции &amp;lt;math&amp;gt;O(C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
* Обновлене матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;O(C*C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
Общая сложность каждой итерации &amp;lt;math&amp;gt;O(C*C*K)&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;
&#039;&#039;&#039;Первый ярус&#039;&#039;&#039; состоит из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; параллельных операций, каждая их которых в свою очередь состоит из &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; параллельных операций, и одной, которая выполняется с использованием результата предыдущих.&lt;br /&gt;
Результатом работы этого яруса является значение &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; , которое будет использоваться на следующем ярусе.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй ярус&#039;&#039;&#039; содержит в себе &amp;lt;math&amp;gt;C*K&amp;lt;/math&amp;gt; параллельных операций.&lt;br /&gt;
Результатом его работы является значение решающей функции &amp;lt;math&amp;gt;J&amp;lt;/math&amp;gt;, значение которой влияет на необходимость завершения алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Третий ярус&#039;&#039;&#039; включает &amp;lt;math&amp;gt;C*K&amp;lt;/math&amp;gt; параллельных операций, каждая из которых состоит из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; параллельных операций, и одной, которая выполняется с использованием результата предыдущих.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Снимок экрана 2016-10-15 в 23.10.05.png|582 px|thumb|center|Информационный граф]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Входные данные:&lt;br /&gt;
* &amp;lt;math&amp;gt;u_{k} k = 1, ..., K&amp;lt;/math&amp;gt; - набор входных векторов;&lt;br /&gt;
* &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; - количество кластеров;&lt;br /&gt;
* &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость;&lt;br /&gt;
* &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0, ~\delta &amp;gt; 0&amp;lt;/math&amp;gt; - коэффициенты, описывающие точность алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные:&lt;br /&gt;
* &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; - матрица принадлежности.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
*Соотношение последовательной и параллельной сложности алгоритма: &amp;lt;math&amp;gt;C*C*K \over {\log_{2} {K} + \log_{2} C^4}&amp;lt;/math&amp;gt;. Соответственно при распараллеливании наибольший прирост в производительности мы получим при разбиении большого набора данных на большее число кластеров;&lt;br /&gt;
*Вычислительная мощность: &amp;lt;math&amp;gt;{{C^2*K} \over {C*K}} = C&amp;lt;/math&amp;gt;. Получается, что на чем большее количество кластеров мы разбиваем набор данных, тем менее затратным становится перемещение данных;&lt;br /&gt;
*Алгоритм не является устойчивым, как и другие подобные алгоритмы этого класса(например k-means). Очень многое зависит как от входных данных, так и от изначальных параметров приближения(заполнения матрицы принадлежности =&amp;gt; исходных центров кластеров);&lt;br /&gt;
*Не является детерминированным. Так же очень многое зависит как от входных данных, так и от изначальных параметров приближения(заполнения матрицы принадлежности =&amp;gt; исходных центров кластеров);&lt;br /&gt;
*Алгоритм не сбалансирован - доминирует операция умножения. Параллельные ветви алгоритма сбалансированы;&lt;br /&gt;
*Степень исхода вершины информационного графа - 2.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Можно найти следующие реализации алгоритма&lt;br /&gt;
* Для MATLAB http://www.mathworks.com/help/fuzzy/fcm.html &lt;br /&gt;
* В PostgreSQL http://num-meth.srcc.msu.ru/zhurnal/tom_2012/v13r207.html&lt;br /&gt;
Так же готовые реализации алгоритма и его описание можно найти на сайтах&lt;br /&gt;
* https://habrahabr.ru/post/208496/&lt;br /&gt;
* http://pythonhosted.org/scikit-fuzzy/auto_examples/plot_cmeans.html&lt;br /&gt;
* http://www.codeproject.com/Articles/91675/Computer-Vision-Applications-with-C-Fuzzy-C-means&lt;br /&gt;
* https://github.com/gyaikhom/fcm&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>ADovganich</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=11272</id>
		<title>Участник:ADovganich/Нечеткий алгоритм С средних</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=11272"/>
		<updated>2016-10-15T19:03:58Z</updated>

		<summary type="html">&lt;p&gt;ADovganich: /* Свойства алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &lt;br /&gt;
| input_data         = &lt;br /&gt;
| output_data          = &lt;br /&gt;
| pf_height        = &lt;br /&gt;
| pf_width       = &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Protsenko|Мария Проценко]] (1.5-1.8, 1.10, 2.7), [[Участник:ADovganich|Андрей Довганич]] (1.1-1.4, 1.9)&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Нечеткий алгоритм C-средних (fuzzy C-means) позволяет разбить имеющееся множество векторов (точек) мощностью p на заданное число нечетких множеств. Предназначен для кластеризации больших наборов данных. Основным достоинством алгоритма является нечеткость при определении объекта в кластер. Благодаря этому становится возможным определить объекты, которые находятся на границе, в кластеры. Из основного достоинства следует и главный недостаток - неопределенность с объектами, удаленными от центров всех кластеров. В остальном ему присущи стандартные проблемы подобного класса алгоритмов: вычислительная сложность, необходимость задания количества кластеров&amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм был разработан J.C. Dunn в 1973 г.&amp;lt;ref&amp;gt; Dunn, J. C. (1973-01-01). &amp;quot;A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters&amp;quot;. Journal of Cybernetics. 3 (3): 32–57. doi:10.1080/01969727308546046. ISSN 0022-0280.&amp;lt;/ref&amp;gt;, усовершенствован J.C. Bezdek в 1981 г.&amp;lt;ref&amp;gt; Bezdek, James C. (1981). Pattern Recognition with Fuzzy Objective Function Algorithms. ISBN 0-306-40671-3.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
На вход алгоритм получает некоторое множество входных векторов и случайную матрицу их принадлежности к каждому из кластеров. На выходе с заданной точностью получаем матрицу принадлежности.&lt;br /&gt;
&lt;br /&gt;
В общем виде алгоритм можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
1) Инициализировать матрицу принадлежности;&lt;br /&gt;
&lt;br /&gt;
2) Вычислить центры кластеров;&lt;br /&gt;
&lt;br /&gt;
3) Вычислить значение решающей функции. Если значение ниже некоторого порогового или его улучшение по сравнению с предыдущей итерацией меньше определенной величины, то остановить вычисления;&lt;br /&gt;
&lt;br /&gt;
4) Иначе вычислить новые значения матрицы принадлежности;&lt;br /&gt;
&lt;br /&gt;
5) Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим матрицу &amp;lt;math&amp;gt; M = m_{ik} \in[0,1],\;  i = 1, ..., c, \; k = 1, ..., K &amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;m_{i,k}&amp;lt;/math&amp;gt; - вероятность принадлежности объекта &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; - количество векторов. При этом элементы матрицы удовлетворяют следующим условиям:&lt;br /&gt;
&lt;br /&gt;
- сумма элементов в каждом столбце равна &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
- сумма всех элементов матрицы равно &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Назовем &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; матрицей принадлежности.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; - центры кластеров. Тогда рассмотрим функцию &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
J(M, c_{1}, c_{2},...c_{c}) = \sum_{i = 1}^{c}{J_{i}} = \sum_{i = 1}^{c}\sum_{k = 1}^{K}{m_{ik}^q}d_{ik}^2 ~(1)&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt; d_{ik} = \left\Vert{u_{k}-c_{i}}\right\| &amp;lt;/math&amp;gt; - Евклидово расстояние между центром кластера и объектом, &amp;lt;math&amp;gt; 1 \le q \le \infty &amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость. Будем минимизировать значение функции &amp;lt;math&amp;gt; J &amp;lt;/math&amp;gt;. Для этого вычислим центры кластеров по формуле &amp;lt;math&amp;gt; ~(2) &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c_{i} = {{\sum_{k = 1}^{K}{m_{ik}^q} * u_{k}} \over {\sum_{k = 1}^{K}{m_{ik}^q}}}~(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;m_{ik}&amp;lt;/math&amp;gt; — коэффициент принадлежности &amp;lt;math&amp;gt;u_{k}&amp;lt;/math&amp;gt; вектора к кластеру &amp;lt;math&amp;gt;c_{i}&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
и новые значения матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; по формуле &amp;lt;math&amp;gt; ~(3) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;m_{ik} = {1 \over \sum_{j = 1}^{c}{({{d_{ik}} \over {d_{jk}}})}^{2 \over q-1}} ~(3)&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; ~(2) &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; ~(3) &amp;lt;/math&amp;gt;являются необходимым условиями достижения минимума функцией &amp;lt;math&amp;gt; J &amp;lt;/math&amp;gt;. Таким образом эти два условия дают нам итерационный процесс.&lt;br /&gt;
&lt;br /&gt;
Полностью алгоритм можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
1) Инициализировать матрицу принадлежности &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; случайными значениями от 0 до 1;&lt;br /&gt;
&lt;br /&gt;
2) Вычислить центры кластеров &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&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;~(1)&amp;lt;/math&amp;gt;. Если значение &amp;lt;math&amp;gt; J &amp;lt; \varepsilon,~\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt; |J_{i} - J_{i-1}| &amp;lt; \delta,~\delta &amp;gt; 0 &amp;lt;/math&amp;gt;, то остановить вычисления;&lt;br /&gt;
&lt;br /&gt;
4) Иначе вычислить новые значения матрицы М по формуле &amp;lt;math&amp;gt;~(3)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
5) Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительным ядром алгоритма являются формулы: &amp;lt;math&amp;gt; (1) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (2) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (3) &amp;lt;/math&amp;gt;. В них производится вычисление новых центров кластеров, значения решающей функции и пересчет элементов матрицы принадлежности.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Макроструктура алгоритма состоит из следующих шагов:&lt;br /&gt;
&lt;br /&gt;
1) Инициализация матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; случайными значениями от 0 до 1;&lt;br /&gt;
&lt;br /&gt;
2) Вычисление центров кластеров; &lt;br /&gt;
&lt;br /&gt;
3) Вычисление значения решающей функции(если оно удовлетворяет условиям останова - завершение вычислений);&lt;br /&gt;
&lt;br /&gt;
4) Вычисление новых элементов матрицы принадлежности;&lt;br /&gt;
&lt;br /&gt;
5) Переход к шагу 2;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации алгоритма на языке С++&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    float ** m;&lt;br /&gt;
    int *c;&lt;br /&gt;
    int number_clusters, number_items;&lt;br /&gt;
    m = gen_random_clusters();//заполним матрицу m случайными значениями от 0 до 1&lt;br /&gt;
    &lt;br /&gt;
    while (true)&lt;br /&gt;
    {&lt;br /&gt;
      //вычисление центров кластеров&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
        {&lt;br /&gt;
            numerator==denumerator=0;&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
            {&lt;br /&gt;
                numerator+=pow(m[i, k], q)*u[k];//u[k]-вектор&lt;br /&gt;
                denumerator+=pow(m[i, k], q);&lt;br /&gt;
            }&lt;br /&gt;
        c[i]= numerator / denumerator;//центры кластеров&lt;br /&gt;
        }&lt;br /&gt;
    &lt;br /&gt;
        j=0;//вычисление решающей функции&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
                j+=pow(m[i, k], q)*pow(dist(c[i], x[k],2);//dist-вычисляет расстояние между заданными векторами&lt;br /&gt;
    &lt;br /&gt;
       if ((abs(j-last_j)&amp;lt;delta) || (j&amp;lt;eps)) break;//проверка на необходимость завернешения алгоритма&lt;br /&gt;
       last_j=j;&lt;br /&gt;
     //обновление матрицы m&lt;br /&gt;
       for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
          for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
             {&lt;br /&gt;
               m[i,k]=0&lt;br /&gt;
              for(int j=0; j&amp;lt;number_clusters; j++)&lt;br /&gt;
                  m[i,k]+=pow(dist(c[i], x[k])/dist(c[j], x[k]),2/(q-1));&lt;br /&gt;
              m[i,k]=1/m[i,k];&lt;br /&gt;
              }&lt;br /&gt;
                                       &lt;br /&gt;
    }&lt;br /&gt;
    &amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Каждая итерация включает в себя&lt;br /&gt;
* Вычисление центров кластеров &amp;lt;math&amp;gt;O(C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
* Вычисление решающей функции &amp;lt;math&amp;gt;O(C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
* Обновлене матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;O(C*C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
Общая сложность каждой итерации &amp;lt;math&amp;gt;O(C*C*K)&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;
* &amp;lt;math&amp;gt;u_{k} k = 1, ..., K&amp;lt;/math&amp;gt; - набор входных векторов;&lt;br /&gt;
* &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; - количество кластеров;&lt;br /&gt;
* &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость;&lt;br /&gt;
* &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0, ~\delta &amp;gt; 0&amp;lt;/math&amp;gt; - коэффициенты, описывающие точность алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные:&lt;br /&gt;
* &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; - матрица принадлежности.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
*Соотношение последовательной и параллельной сложности алгоритма: &amp;lt;math&amp;gt;C*C*K \over (?)&amp;lt;/math&amp;gt;. Соответственно при распараллеливании наибольший прирост в производительности мы получим при разбиении большого набора данных на большее число кластеров;&lt;br /&gt;
*Вычислительная мощность: &amp;lt;math&amp;gt;{{C^2*K} \over {C*K}} = C&amp;lt;/math&amp;gt;. Получается, что на чем большее количество кластеров мы разбиваем набор данных, тем менее затратным становится перемещение данных;&lt;br /&gt;
*Алгоритм не является устойчивым, как и другие подобные алгоритмы этого класса(например k-means). Очень многое зависит как от входных данных, так и от изначальных параметров приближения(заполнения матрицы принадлежности =&amp;gt; исходных центров кластеров);&lt;br /&gt;
*Не является детерминированным. Так же очень многое зависит как от входных данных, так и от изначальных параметров приближения(заполнения матрицы принадлежности =&amp;gt; исходных центров кластеров);&lt;br /&gt;
*Алгоритм не сбалансирован - доминирует операция умножения. Параллельные ветви алгоритма сбалансированы;&lt;br /&gt;
*Степень исхода вершины информационного графа - 2.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Можно найти следующие реализации алгоритма&lt;br /&gt;
* Для MATLAB http://www.mathworks.com/help/fuzzy/fcm.html &lt;br /&gt;
* В PostgreSQL http://num-meth.srcc.msu.ru/zhurnal/tom_2012/v13r207.html&lt;br /&gt;
Так же готовые реализации алгоритма и его описание можно найти на сайтах&lt;br /&gt;
* https://habrahabr.ru/post/208496/&lt;br /&gt;
* http://pythonhosted.org/scikit-fuzzy/auto_examples/plot_cmeans.html&lt;br /&gt;
* http://www.codeproject.com/Articles/91675/Computer-Vision-Applications-with-C-Fuzzy-C-means&lt;br /&gt;
* https://github.com/gyaikhom/fcm&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>ADovganich</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=11218</id>
		<title>Участник:ADovganich/Нечеткий алгоритм С средних</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=11218"/>
		<updated>2016-10-15T18:55:05Z</updated>

		<summary type="html">&lt;p&gt;ADovganich: /* Свойства алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &lt;br /&gt;
| input_data         = &lt;br /&gt;
| output_data          = &lt;br /&gt;
| pf_height        = &lt;br /&gt;
| pf_width       = &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Protsenko|Мария Проценко]] (1.5-1.8, 1.10, 2.7), [[Участник:ADovganich|Андрей Довганич]] (1.1-1.4, 1.9)&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Нечеткий алгоритм C-средних (fuzzy C-means) позволяет разбить имеющееся множество векторов (точек) мощностью p на заданное число нечетких множеств. Предназначен для кластеризации больших наборов данных. Основным достоинством алгоритма является нечеткость при определении объекта в кластер. Благодаря этому становится возможным определить объекты, которые находятся на границе, в кластеры. Из основного достоинства следует и главный недостаток - неопределенность с объектами, удаленными от центров всех кластеров. В остальном ему присущи стандартные проблемы подобного класса алгоритмов: вычислительная сложность, необходимость задания количества кластеров&amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм был разработан J.C. Dunn в 1973 г.&amp;lt;ref&amp;gt; Dunn, J. C. (1973-01-01). &amp;quot;A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters&amp;quot;. Journal of Cybernetics. 3 (3): 32–57. doi:10.1080/01969727308546046. ISSN 0022-0280.&amp;lt;/ref&amp;gt;, усовершенствован J.C. Bezdek в 1981 г.&amp;lt;ref&amp;gt; Bezdek, James C. (1981). Pattern Recognition with Fuzzy Objective Function Algorithms. ISBN 0-306-40671-3.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
На вход алгоритм получает некоторое множество входных векторов и случайную матрицу их принадлежности к каждому из кластеров. На выходе с заданной точностью получаем матрицу принадлежности.&lt;br /&gt;
&lt;br /&gt;
В общем виде алгоритм можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
1) Инициализировать матрицу принадлежности;&lt;br /&gt;
&lt;br /&gt;
2) Вычислить центры кластеров;&lt;br /&gt;
&lt;br /&gt;
3) Вычислить значение решающей функции. Если значение ниже некоторого порогового или его улучшение по сравнению с предыдущей итерацией меньше определенной величины, то остановить вычисления;&lt;br /&gt;
&lt;br /&gt;
4) Иначе вычислить новые значения матрицы принадлежности;&lt;br /&gt;
&lt;br /&gt;
5) Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим матрицу &amp;lt;math&amp;gt; M = m_{ik} \in[0,1],\;  i = 1, ..., c, \; k = 1, ..., K &amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;m_{i,k}&amp;lt;/math&amp;gt; - вероятность принадлежности объекта &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; - количество векторов. При этом элементы матрицы удовлетворяют следующим условиям:&lt;br /&gt;
&lt;br /&gt;
- сумма элементов в каждом столбце равна &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
- сумма всех элементов матрицы равно &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Назовем &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; матрицей принадлежности.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; - центры кластеров. Тогда рассмотрим функцию &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
J(M, c_{1}, c_{2},...c_{c}) = \sum_{i = 1}^{c}{J_{i}} = \sum_{i = 1}^{c}\sum_{k = 1}^{K}{m_{ik}^q}d_{ik}^2 ~(1)&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt; d_{ik} = \left\Vert{u_{k}-c_{i}}\right\| &amp;lt;/math&amp;gt; - Евклидово расстояние между центром кластера и объектом, &amp;lt;math&amp;gt; 1 \le q \le \infty &amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость. Будем минимизировать значение функции &amp;lt;math&amp;gt; J &amp;lt;/math&amp;gt;. Для этого вычислим центры кластеров по формуле &amp;lt;math&amp;gt; ~(2) &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c_{i} = {{\sum_{k = 1}^{K}{m_{ik}^q} * u_{k}} \over {\sum_{k = 1}^{K}{m_{ik}^q}}}~(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;m_{ik}&amp;lt;/math&amp;gt; — коэффициент принадлежности &amp;lt;math&amp;gt;u_{k}&amp;lt;/math&amp;gt; вектора к кластеру &amp;lt;math&amp;gt;c_{i}&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
и новые значения матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; по формуле &amp;lt;math&amp;gt; ~(3) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;m_{ik} = {1 \over \sum_{j = 1}^{c}{({{d_{ik}} \over {d_{jk}}})}^{2 \over q-1}} ~(3)&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; ~(2) &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; ~(3) &amp;lt;/math&amp;gt;являются необходимым условиями достижения минимума функцией &amp;lt;math&amp;gt; J &amp;lt;/math&amp;gt;. Таким образом эти два условия дают нам итерационный процесс.&lt;br /&gt;
&lt;br /&gt;
Полностью алгоритм можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
1) Инициализировать матрицу принадлежности &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; случайными значениями от 0 до 1;&lt;br /&gt;
&lt;br /&gt;
2) Вычислить центры кластеров &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&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;~(1)&amp;lt;/math&amp;gt;. Если значение &amp;lt;math&amp;gt; J &amp;lt; \varepsilon,~\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt; |J_{i} - J_{i-1}| &amp;lt; \delta,~\delta &amp;gt; 0 &amp;lt;/math&amp;gt;, то остановить вычисления;&lt;br /&gt;
&lt;br /&gt;
4) Иначе вычислить новые значения матрицы М по формуле &amp;lt;math&amp;gt;~(3)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
5) Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительным ядром алгоритма являются формулы: &amp;lt;math&amp;gt; (1) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (2) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (3) &amp;lt;/math&amp;gt;. В них производится вычисление новых центров кластеров, значения решающей функции и пересчет элементов матрицы принадлежности.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Макроструктура алгоритма состоит из следующих шагов:&lt;br /&gt;
&lt;br /&gt;
1) Инициализация матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; случайными значениями от 0 до 1;&lt;br /&gt;
&lt;br /&gt;
2) Вычисление центров кластеров; &lt;br /&gt;
&lt;br /&gt;
3) Вычисление значения решающей функции(если оно удовлетворяет условиям останова - завершение вычислений);&lt;br /&gt;
&lt;br /&gt;
4) Вычисление новых элементов матрицы принадлежности;&lt;br /&gt;
&lt;br /&gt;
5) Переход к шагу 2;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации алгоритма на языке С++&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    float ** m;&lt;br /&gt;
    int *c;&lt;br /&gt;
    int number_clusters, number_items;&lt;br /&gt;
    m = gen_random_clusters();//заполним матрицу m случайными значениями от 0 до 1&lt;br /&gt;
    &lt;br /&gt;
    while (true)&lt;br /&gt;
    {&lt;br /&gt;
      //вычисление центров кластеров&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
        {&lt;br /&gt;
            numerator==denumerator=0;&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
            {&lt;br /&gt;
                numerator+=pow(m[i, k], q)*u[k];//u[k]-вектор&lt;br /&gt;
                denumerator+=pow(m[i, k], q);&lt;br /&gt;
            }&lt;br /&gt;
        c[i]= numerator / denumerator;//центры кластеров&lt;br /&gt;
        }&lt;br /&gt;
    &lt;br /&gt;
        j=0;//вычисление решающей функции&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
                j+=pow(m[i, k], q)*pow(dist(c[i], x[k],2);//dist-вычисляет расстояние между заданными векторами&lt;br /&gt;
    &lt;br /&gt;
       if ((abs(j-last_j)&amp;lt;delta) || (j&amp;lt;eps)) break;//проверка на необходимость завернешения алгоритма&lt;br /&gt;
       last_j=j;&lt;br /&gt;
     //обновление матрицы m&lt;br /&gt;
       for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
          for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
             {&lt;br /&gt;
               m[i,k]=0&lt;br /&gt;
              for(int j=0; j&amp;lt;number_clusters; j++)&lt;br /&gt;
                  m[i,k]+=pow(dist(c[i], x[k])/dist(c[j], x[k]),2/(q-1));&lt;br /&gt;
              m[i,k]=1/m[i,k];&lt;br /&gt;
              }&lt;br /&gt;
                                       &lt;br /&gt;
    }&lt;br /&gt;
    &amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Каждая итерация включает в себя&lt;br /&gt;
* Вычисление центров кластеров &amp;lt;math&amp;gt;O(C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
* Вычисление решающей функции &amp;lt;math&amp;gt;O(C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
* Обновлене матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;O(C*C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
Общая сложность каждой итерации &amp;lt;math&amp;gt;O(C*C*K)&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;
* &amp;lt;math&amp;gt;u_{k} k = 1, ..., K&amp;lt;/math&amp;gt; - набор входных векторов;&lt;br /&gt;
* &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; - количество кластеров;&lt;br /&gt;
* &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость;&lt;br /&gt;
* &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0, ~\delta &amp;gt; 0&amp;lt;/math&amp;gt; - коэффициенты, описывающие точность алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные:&lt;br /&gt;
* &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; - матрица принадлежности.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
*Соотношение последовательной и параллельной сложности алгоритма: &amp;lt;math&amp;gt;C*C*K \over (?)&amp;lt;/math&amp;gt;. Соответственно при распараллеливании наибольший прирост в производительности мы получим при разбиении большого набора данных на большее число кластеров;&lt;br /&gt;
*Вычислительная мощность: &amp;lt;math&amp;gt;{{C^2*K} \over {C*K}} = C&amp;lt;/math&amp;gt;. Получается, что на чем большее количество кластеров мы разбиваем набор данных, тем менее затратным становится перемещение данных;&lt;br /&gt;
*Алгоритм не является устойчивым, как и другие подобные алгоритмы этого класса(например k-means). Очень многое зависит как от входных данных, так и от изначальных параметров приближения(заполнения матрицы принадлежности =&amp;gt; исходных центров кластеров);&lt;br /&gt;
*Не является детерминированным. Так же jчень многое зависит как от входных данных, так и от изначальных параметров приближения(заполнения матрицы принадлежности =&amp;gt; исходных центров кластеров);&lt;br /&gt;
*Алгоритм не сбалансирован - доминирует операция умножения. Параллельные ветви алгоритма сбалансированы;&lt;br /&gt;
*Степень исхода вершины информационного графа - 2.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Можно найти следующие реализации алгоритма&lt;br /&gt;
* Для MATLAB http://www.mathworks.com/help/fuzzy/fcm.html &lt;br /&gt;
* В PostgreSQL http://num-meth.srcc.msu.ru/zhurnal/tom_2012/v13r207.html&lt;br /&gt;
Так же готовые реализации алгоритма и его описание можно найти на сайтах&lt;br /&gt;
* https://habrahabr.ru/post/208496/&lt;br /&gt;
* http://pythonhosted.org/scikit-fuzzy/auto_examples/plot_cmeans.html&lt;br /&gt;
* http://www.codeproject.com/Articles/91675/Computer-Vision-Applications-with-C-Fuzzy-C-means&lt;br /&gt;
* https://github.com/gyaikhom/fcm&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>ADovganich</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=8514</id>
		<title>Участник:ADovganich/Нечеткий алгоритм С средних</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=8514"/>
		<updated>2016-10-14T23:52:18Z</updated>

		<summary type="html">&lt;p&gt;ADovganich: /* Входные и выходные данные алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &lt;br /&gt;
| input_data         = &lt;br /&gt;
| output_data          = &lt;br /&gt;
| pf_height        = &lt;br /&gt;
| pf_width       = &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Protsenko|Мария Проценко]] (1.5-1.10, 2.7), [[Участник:ADovganich|Андрей Довганич]] (1.1-1.4)&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Нечеткий алгоритм C-средних (fuzzy C-means) позволяет разбить имеющееся множество векторов (точек) мощностью p на заданное число нечетких множеств. Предназначен для кластеризации больших наборов данных. Основным достоинством алгоритма является нечеткость при определении объекта в кластер. Благодаря этому становится возможным определить объекты, которые находятся на границе, в кластеры. Из основного достоинства следует и главный недостаток - неопределенность с объектами, удаленными от центров всех кластеров. В остальном ему присущи стандартные проблемы подобного класса алгоритмов: вычислительная сложность, необходимость задания количества кластеров&amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм был разработан J.C. Dunn в 1973 г.&amp;lt;ref&amp;gt; Dunn, J. C. (1973-01-01). &amp;quot;A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters&amp;quot;. Journal of Cybernetics. 3 (3): 32–57. doi:10.1080/01969727308546046. ISSN 0022-0280.&amp;lt;/ref&amp;gt;, усовершенствован J.C. Bezdek в 1981 г.&amp;lt;ref&amp;gt; Bezdek, James C. (1981). Pattern Recognition with Fuzzy Objective Function Algorithms. ISBN 0-306-40671-3.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
На вход алгоритм получает некоторое множество входных векторов и случайную матрицу их принадлежности к каждому из кластеров. На выходе с заданной точностью получаем матрицу принадлежности.&lt;br /&gt;
&lt;br /&gt;
В общем виде алгоритм можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
1) Инициализировать матрицу принадлежности;&lt;br /&gt;
&lt;br /&gt;
2) Вычислить центры кластеров;&lt;br /&gt;
&lt;br /&gt;
3) Вычислить значение решающей функции. Если значение ниже некоторого порогового или его улучшение по сравнению с предыдущей итерацией меньше определенной величины, то остановить вычисления;&lt;br /&gt;
&lt;br /&gt;
4) Иначе вычислить новые значения матрицы принадлежности;&lt;br /&gt;
&lt;br /&gt;
5) Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим матрицу &amp;lt;math&amp;gt; M = m_{ik} \in[0,1],\;  i = 1, ..., c, \; k = 1, ..., K &amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;m_{i,k}&amp;lt;/math&amp;gt; - вероятность принадлежности объекта &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; - количество векторов. При этом элементы матрицы удовлетворяют следующим условиям:&lt;br /&gt;
&lt;br /&gt;
- сумма элементов в каждом столбце равна &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
- сумма всех элементов матрицы равно &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Назовем &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; матрицей принадлежности.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; - центры кластеров. Тогда рассмотрим функцию &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
J(M, c_{1}, c_{2},...c_{c}) = \sum_{i = 1}^{c}{J_{i}} = \sum_{i = 1}^{c}\sum_{k = 1}^{K}{m_{ik}^q}d_{ik}^2 ~(1)&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt; d_{ik} = \left\Vert{u_{k}-c_{i}}\right\| &amp;lt;/math&amp;gt; - Евклидово расстояние между центром кластера и объектом, &amp;lt;math&amp;gt; 1 \le q \le \infty &amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость. Будем минимизировать значение функции &amp;lt;math&amp;gt; J &amp;lt;/math&amp;gt;. Для этого вычислим центры кластеров по формуле &amp;lt;math&amp;gt; ~(2) &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c_{i} = {{\sum_{k = 1}^{K}{m_{ik}^q} * u_{k}} \over {\sum_{k = 1}^{K}{m_{ik}^q}}}~(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;m_{ik}&amp;lt;/math&amp;gt; — коэффициент принадлежности &amp;lt;math&amp;gt;u_{k}&amp;lt;/math&amp;gt; вектора к кластеру &amp;lt;math&amp;gt;c_{i}&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
и новые значения матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; по формуле &amp;lt;math&amp;gt; ~(3) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;m_{ik} = {1 \over \sum_{j = 1}^{c}{({{d_{ik}} \over {d_{jk}}})}^{2 \over q-1}} ~(3)&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; ~(2) &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; ~(3) &amp;lt;/math&amp;gt;являются необходимым условиями достижения минимума функцией &amp;lt;math&amp;gt; J &amp;lt;/math&amp;gt;. Таким образом эти два условия дают нам итерационный процесс.&lt;br /&gt;
&lt;br /&gt;
Полностью алгоритм можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
1) Инициализировать матрицу принадлежности &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; случайными значениями от 0 до 1;&lt;br /&gt;
&lt;br /&gt;
2) Вычислить центры кластеров &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&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;~(1)&amp;lt;/math&amp;gt;. Если значение &amp;lt;math&amp;gt; J &amp;lt; \varepsilon,~\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt; |J_{i} - J_{i-1}| &amp;lt; \delta,~\delta &amp;gt; 0 &amp;lt;/math&amp;gt;, то остановить вычисления;&lt;br /&gt;
&lt;br /&gt;
4) Иначе вычислить новые значения матрицы М по формуле &amp;lt;math&amp;gt;~(3)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
5) Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительным ядром алгоритма являются формулы: &amp;lt;math&amp;gt; (1) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (2) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (3) &amp;lt;/math&amp;gt;. В них производится вычисление новых центров кластеров, значения решающей функции и пересчет элементов матрицы принадлежности.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Макроструктура алгоритма состоит из следующих шагов:&lt;br /&gt;
&lt;br /&gt;
1) Инициализация матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; случайными значениями от 0 до 1;&lt;br /&gt;
&lt;br /&gt;
2) Вычисление центров кластеров; &lt;br /&gt;
&lt;br /&gt;
3) Вычисление значения решающей функции(если оно удовлетворяет условиям останова - завершение вычислений);&lt;br /&gt;
&lt;br /&gt;
4) Вычисление новых элементов матрицы принадлежности;&lt;br /&gt;
&lt;br /&gt;
5) Переход к шагу 2;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации алгоритма на языке С++&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    float ** m;&lt;br /&gt;
    int *c;&lt;br /&gt;
    int number_clusters, number_items;&lt;br /&gt;
    m = gen_random_clusters();//заполним матрицу m случайными значениями от 0 до 1&lt;br /&gt;
    &lt;br /&gt;
    while (true)&lt;br /&gt;
    {&lt;br /&gt;
      //вычисление центров кластеров&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
        {&lt;br /&gt;
            numerator==denumerator=0;&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
            {&lt;br /&gt;
                numerator+=pow(m[i, k], q)*u[k];//u[k]-вектор&lt;br /&gt;
                denumerator+=pow(m[i, k], q);&lt;br /&gt;
            }&lt;br /&gt;
        c[i]= numerator / denumerator;//центры кластеров&lt;br /&gt;
        }&lt;br /&gt;
    &lt;br /&gt;
        j=0;//вычисление решающей функции&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
                j+=pow(m[i, k], q)*pow(dist(c[i], x[k],2);//dist-вычисляет расстояние между заданными векторами&lt;br /&gt;
    &lt;br /&gt;
       if ((abs(j-last_j)&amp;lt;eps1) || (j&amp;lt;eps2)) break;//проверка на необходимость завернешения алгоритма&lt;br /&gt;
       last_j=j;&lt;br /&gt;
     //обновление матрицы m&lt;br /&gt;
       for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
          for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
             {&lt;br /&gt;
               m[i,k]=0&lt;br /&gt;
              for(int j=0; j&amp;lt;number_clusters; j++)&lt;br /&gt;
                  m[i,k]=pow(dist(c[i], x[k]),2/(q-1));&lt;br /&gt;
                 m[i,k]=1/m[i,k];&lt;br /&gt;
              }&lt;br /&gt;
                                       &lt;br /&gt;
    }&lt;br /&gt;
    &amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Каждая итерация включает в себя&lt;br /&gt;
* Вычисление центров кластеров &amp;lt;math&amp;gt;O(C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
* Вычисление решающей функции &amp;lt;math&amp;gt;O(C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
* Обновлене матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;O(C*C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
Общая сложность каждой итерации &amp;lt;math&amp;gt;O(C*C*K)&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;
* &amp;lt;math&amp;gt;u_{k} k = 1, ..., K&amp;lt;/math&amp;gt; - набор входных векторов;&lt;br /&gt;
* &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; - количество кластеров;&lt;br /&gt;
* &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость;&lt;br /&gt;
* &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0, ~\delta &amp;gt; 0&amp;lt;/math&amp;gt; - коэффициенты, описывающие точность алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выходные данные:&lt;br /&gt;
* &amp;lt;math&amp;gt; M &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;
* Для MATLAB &amp;lt;ref&amp;gt;http://www.mathworks.com/help/fuzzy/fcm.html &amp;lt;/ref&amp;gt;&lt;br /&gt;
* В PostgreSQL &amp;lt;ref&amp;gt;http://num-meth.srcc.msu.ru/zhurnal/tom_2012/v13r207.html&amp;lt;/ref&amp;gt;&lt;br /&gt;
Так же готовые реализации алгоритма и его описание можно найти на сайтах&lt;br /&gt;
* https://habrahabr.ru/post/208496/&lt;br /&gt;
* http://pythonhosted.org/scikit-fuzzy/auto_examples/plot_cmeans.html&lt;br /&gt;
* http://www.codeproject.com/Articles/91675/Computer-Vision-Applications-with-C-Fuzzy-C-means&lt;br /&gt;
* https://github.com/gyaikhom/fcm&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>ADovganich</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=8505</id>
		<title>Участник:ADovganich/Нечеткий алгоритм С средних</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=8505"/>
		<updated>2016-10-14T23:43:01Z</updated>

		<summary type="html">&lt;p&gt;ADovganich: /* Математическое описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &lt;br /&gt;
| input_data         = &lt;br /&gt;
| output_data          = &lt;br /&gt;
| pf_height        = &lt;br /&gt;
| pf_width       = &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Protsenko|Мария Проценко]] (1.5-1.10, 2.7), [[Участник:ADovganich|Андрей Довганич]] (1.1-1.4)&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Нечеткий алгоритм C-средних (fuzzy C-means) позволяет разбить имеющееся множество векторов (точек) мощностью p на заданное число нечетких множеств. Предназначен для кластеризации больших наборов данных. Основным достоинством алгоритма является нечеткость при определении объекта в кластер. Благодаря этому становится возможным определить объекты, которые находятся на границе, в кластеры. Из основного достоинства следует и главный недостаток - неопределенность с объектами, удаленными от центров всех кластеров. В остальном ему присущи стандартные проблемы подобного класса алгоритмов: вычислительная сложность, необходимость задания количества кластеров&amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм был разработан J.C. Dunn в 1973 г.&amp;lt;ref&amp;gt; Dunn, J. C. (1973-01-01). &amp;quot;A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters&amp;quot;. Journal of Cybernetics. 3 (3): 32–57. doi:10.1080/01969727308546046. ISSN 0022-0280.&amp;lt;/ref&amp;gt;, усовершенствован J.C. Bezdek в 1981 г.&amp;lt;ref&amp;gt; Bezdek, James C. (1981). Pattern Recognition with Fuzzy Objective Function Algorithms. ISBN 0-306-40671-3.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
На вход алгоритм получает некоторое множество входных векторов и случайную матрицу их принадлежности к каждому из кластеров. На выходе с заданной точностью получаем матрицу принадлежности.&lt;br /&gt;
&lt;br /&gt;
В общем виде алгоритм можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
1) Инициализировать матрицу принадлежности;&lt;br /&gt;
&lt;br /&gt;
2) Вычислить центры кластеров;&lt;br /&gt;
&lt;br /&gt;
3) Вычислить значение решающей функции. Если значение ниже некоторого порогового или его улучшение по сравнению с предыдущей итерацией меньше определенной величины, то остановить вычисления;&lt;br /&gt;
&lt;br /&gt;
4) Иначе вычислить новые значения матрицы принадлежности;&lt;br /&gt;
&lt;br /&gt;
5) Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим матрицу &amp;lt;math&amp;gt; M = m_{ik} \in[0,1],\;  i = 1, ..., c, \; k = 1, ..., K &amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;m_{i,k}&amp;lt;/math&amp;gt; - вероятность принадлежности объекта &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; - количество векторов. При этом элементы матрицы удовлетворяют следующим условиям:&lt;br /&gt;
&lt;br /&gt;
- сумма элементов в каждом столбце равна &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
- сумма всех элементов матрицы равно &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Назовем &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; матрицей принадлежности.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; - центры кластеров. Тогда рассмотрим функцию &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
J(M, c_{1}, c_{2},...c_{c}) = \sum_{i = 1}^{c}{J_{i}} = \sum_{i = 1}^{c}\sum_{k = 1}^{K}{m_{ik}^q}d_{ik}^2 ~(1)&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt; d_{ik} = \left\Vert{u_{k}-c_{i}}\right\| &amp;lt;/math&amp;gt; - Евклидово расстояние между центром кластера и объектом, &amp;lt;math&amp;gt; 1 \le q \le \infty &amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость. Будем минимизировать значение функции &amp;lt;math&amp;gt; J &amp;lt;/math&amp;gt;. Для этого вычислим центры кластеров по формуле &amp;lt;math&amp;gt; ~(2) &amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c_{i} = {{\sum_{k = 1}^{K}{m_{ik}^q} * u_{k}} \over {\sum_{k = 1}^{K}{m_{ik}^q}}}~(2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;m_{ik}&amp;lt;/math&amp;gt; — коэффициент принадлежности &amp;lt;math&amp;gt;u_{k}&amp;lt;/math&amp;gt; вектора к кластеру &amp;lt;math&amp;gt;c_{i}&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
и новые значения матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; по формуле &amp;lt;math&amp;gt; ~(3) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;m_{ik} = {1 \over \sum_{j = 1}^{c}{({{d_{ik}} \over {d_{jk}}})}^{2 \over q-1}} ~(3)&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; ~(2) &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; ~(3) &amp;lt;/math&amp;gt;являются необходимым условиями достижения минимума функцией &amp;lt;math&amp;gt; J &amp;lt;/math&amp;gt;. Таким образом эти два условия дают нам итерационный процесс.&lt;br /&gt;
&lt;br /&gt;
Полностью алгоритм можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
1) Инициализировать матрицу принадлежности &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; случайными значениями от 0 до 1;&lt;br /&gt;
&lt;br /&gt;
2) Вычислить центры кластеров &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&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;~(1)&amp;lt;/math&amp;gt;. Если значение &amp;lt;math&amp;gt; J &amp;lt; \varepsilon,~\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt; |J_{i} - J_{i-1}| &amp;lt; \delta,~\delta &amp;gt; 0 &amp;lt;/math&amp;gt;, то остановить вычисления;&lt;br /&gt;
&lt;br /&gt;
4) Иначе вычислить новые значения матрицы М по формуле &amp;lt;math&amp;gt;~(3)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
5) Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительным ядром алгоритма являются формулы: &amp;lt;math&amp;gt; (1) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (2) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (3) &amp;lt;/math&amp;gt;. В них производится вычисление новых центров кластеров, значения решающей функции и пересчет элементов матрицы принадлежности.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Макроструктура алгоритма состоит из следующих шагов:&lt;br /&gt;
&lt;br /&gt;
1) Инициализация матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; случайными значениями от 0 до 1;&lt;br /&gt;
&lt;br /&gt;
2) Вычисление центров кластеров; &lt;br /&gt;
&lt;br /&gt;
3) Вычисление значения решающей функции(если оно удовлетворяет условиям останова - завершение вычислений);&lt;br /&gt;
&lt;br /&gt;
4) Вычисление новых элементов матрицы принадлежности;&lt;br /&gt;
&lt;br /&gt;
5) Переход к шагу 2;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации алгоритма на языке С++&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    float ** m;&lt;br /&gt;
    int *c;&lt;br /&gt;
    int number_clusters, number_items;&lt;br /&gt;
    m = gen_random_clusters();//заполним матрицу m случайными значениями от 0 до 1&lt;br /&gt;
    &lt;br /&gt;
    while (true)&lt;br /&gt;
    {&lt;br /&gt;
      //вычисление центров кластеров&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
        {&lt;br /&gt;
            numerator==denumerator=0;&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
            {&lt;br /&gt;
                numerator+=pow(m[i, k], q)*u[k];//u[k]-вектор&lt;br /&gt;
                denumerator+=pow(m[i, k], q);&lt;br /&gt;
            }&lt;br /&gt;
        c[i]= numerator / denumerator;//центры кластеров&lt;br /&gt;
        }&lt;br /&gt;
    &lt;br /&gt;
        j=0;//вычисление решающей функции&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
                j+=pow(m[i, k], q)*pow(dist(c[i], x[k],2);//dist-вычисляет расстояние между заданными векторами&lt;br /&gt;
    &lt;br /&gt;
       if ((abs(j-last_j)&amp;lt;eps1) || (j&amp;lt;eps2)) break;//проверка на необходимость завернешения алгоритма&lt;br /&gt;
       last_j=j;&lt;br /&gt;
     //обновление матрицы m&lt;br /&gt;
       for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
          for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
             {&lt;br /&gt;
               m[i,k]=0&lt;br /&gt;
              for(int j=0; j&amp;lt;number_clusters; j++)&lt;br /&gt;
                  m[i,k]=pow(dist(c[i], x[k]),2/(q-1));&lt;br /&gt;
                 m[i,k]=1/m[i,k];&lt;br /&gt;
              }&lt;br /&gt;
                                       &lt;br /&gt;
    }&lt;br /&gt;
    &amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Каждая итерация включает в себя&lt;br /&gt;
* Вычисление центров кластеров &amp;lt;math&amp;gt;O(C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
* Вычисление решающей функции &amp;lt;math&amp;gt;O(C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
* Обновлене матрицы m &amp;lt;math&amp;gt;O(C*C*K)&amp;lt;/math&amp;gt; &lt;br /&gt;
Общая сложность каждой итерации &amp;lt;math&amp;gt;O(C*C*K)&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;/div&gt;</summary>
		<author><name>ADovganich</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=8464</id>
		<title>Участник:ADovganich/Нечеткий алгоритм С средних</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=8464"/>
		<updated>2016-10-14T23:16:20Z</updated>

		<summary type="html">&lt;p&gt;ADovganich: /* Общее описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &lt;br /&gt;
| input_data         = &lt;br /&gt;
| output_data          = &lt;br /&gt;
| pf_height        = &lt;br /&gt;
| pf_width       = &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Protsenko|Мария Проценко]], [[Участник:ADovganich|Андрей Довганич]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Нечеткий алгоритм C-средних (fuzzy C-means) позволяет разбить имеющееся множество векторов (точек) мощностью p на заданное число нечетких множеств. Предназначен для кластеризации больших наборов данных. Основным достоинством алгоритма является нечеткость при определении объекта в кластер. Благодаря этому становится возможным определить объекты, которые находятся на границе, в кластеры. Из основного достоинства следует и главный недостаток - неопределенность с объектами, удаленными от центров всех кластеров. В остальном ему присущи стандартные проблемы подобного класса алгоритмов: вычислительная сложность, необходимость задания количества кластеров&amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм был разработан J.C. Dunn в 1973 г.&amp;lt;ref&amp;gt; Dunn, J. C. (1973-01-01). &amp;quot;A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters&amp;quot;. Journal of Cybernetics. 3 (3): 32–57. doi:10.1080/01969727308546046. ISSN 0022-0280.&amp;lt;/ref&amp;gt;, усовершенствован J.C. Bezdek в 1981 г.&amp;lt;ref&amp;gt; Bezdek, James C. (1981). Pattern Recognition with Fuzzy Objective Function Algorithms. ISBN 0-306-40671-3.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
На вход алгоритм получает некоторое множество входных векторов и случайную матрицу их принадлежности к каждому из кластеров. На выходе с заданной точностью получаем матрицу принадлежности.&lt;br /&gt;
&lt;br /&gt;
В общем виде алгоритм можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
1) Инициализировать матрицу принадлежности;&lt;br /&gt;
&lt;br /&gt;
2) Вычислить центры кластеров;&lt;br /&gt;
&lt;br /&gt;
3) Вычислить значение решающей функции. Если значение ниже некоторого порогового или его улучшение по сравнению с предыдущей итерацией меньше определенной величины, то остановить вычисления;&lt;br /&gt;
&lt;br /&gt;
4) Иначе вычислить новые значения матрицы принадлежности;&lt;br /&gt;
&lt;br /&gt;
5) Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим матрицу &amp;lt;math&amp;gt; M = m_{ik} \in[0,1],\;  i = 1, ..., c, \; k = 1, ..., K &amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;m_{i,k}&amp;lt;/math&amp;gt; - вероятность принадлежности объекта &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; - количество векторов. При этом элементы матрицы удовлетворяют следующим условиям:&lt;br /&gt;
&lt;br /&gt;
- сумма элементов в каждом столбце равна &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
- сумма всех элементов матрицы равно &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Назовем &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; матрицей принадлежности.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; - центры кластеров. Тогда рассмотрим функцию &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; d_{ik} = \left\Vert{u_{k}-c_{i}}\right\| &amp;lt;/math&amp;gt; - Евклидово расстояние между центром кластера и объектом, &amp;lt;math&amp;gt; 1 \le q \le \infty &amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость. Будем минимизировать значение функции &amp;lt;math&amp;gt; J &amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt; (1) &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; (3) &amp;lt;/math&amp;gt; являются необходимым условие достижения минимума этой функцией. Таким образом эти два условия дают нам итерационный процесс, описанный выше.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительным ядром алгоритма являются формулы: &amp;lt;math&amp;gt; (1) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (2) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (3) &amp;lt;/math&amp;gt;. В них производится вычисление новых центров кластеров, значения решающей функции и пересчет элементов матрицы принадлежности.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Макроструктура алгоритма состоит из следующих шагов:&lt;br /&gt;
&lt;br /&gt;
1) Инициализация матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; случайными значениями от 0 до 1;&lt;br /&gt;
&lt;br /&gt;
2) Вычисление центров кластеров; &lt;br /&gt;
&lt;br /&gt;
3) Вычисление значения решающей функции(если оно удовлетворяет условиям останова - завершение вычислений);&lt;br /&gt;
&lt;br /&gt;
4) Вычисление новых элементов матрицы принадлежности;&lt;br /&gt;
&lt;br /&gt;
5) Переход к шагу 2;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации алгоритма на языке С++&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    float ** m;&lt;br /&gt;
    int *c;&lt;br /&gt;
    int number_clusters, number_items;&lt;br /&gt;
    m = gen_random_clusters();//заполним матрицу m случайными значениями от 0 до 1&lt;br /&gt;
    &lt;br /&gt;
    while (true)&lt;br /&gt;
    {&lt;br /&gt;
      //вычисление центров кластеров&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
        {&lt;br /&gt;
            numerator==denumerator=0;&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
            {&lt;br /&gt;
                numerator+=pow(m[i, k], q)*u[k];//u[k]-вектор&lt;br /&gt;
                denumerator+=pow(m[i, k], q);&lt;br /&gt;
            }&lt;br /&gt;
        c[i]= numerator / denumerator;//центры кластеров&lt;br /&gt;
        }&lt;br /&gt;
    &lt;br /&gt;
        j=0;//вычисление решающей функции&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
                j+=pow(m[i, k], q)*pow(dist(c[i], x[k],2);//dist-вычисляет расстояние между заданными векторами&lt;br /&gt;
    &lt;br /&gt;
       if ((abs(j-last_j)&amp;lt;eps1) || (j&amp;lt;eps2)) break;//проверка на необходимость завернешения алгоритма&lt;br /&gt;
       last_j=j;&lt;br /&gt;
     //обновление матрицы m&lt;br /&gt;
       for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
          for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
             {&lt;br /&gt;
               m[i,k]=0&lt;br /&gt;
              for(int j=0; j&amp;lt;number_clusters; j++)&lt;br /&gt;
                  m[i,k]=pow(dist(c[i], x[k]),2/(q-1));&lt;br /&gt;
                 m[i,k]=1/m[i,k];&lt;br /&gt;
              }&lt;br /&gt;
                                       &lt;br /&gt;
    }&lt;br /&gt;
    &amp;lt;/source&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;/div&gt;</summary>
		<author><name>ADovganich</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=8460</id>
		<title>Участник:ADovganich/Нечеткий алгоритм С средних</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=8460"/>
		<updated>2016-10-14T23:10:38Z</updated>

		<summary type="html">&lt;p&gt;ADovganich: /* Макроструктура алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &lt;br /&gt;
| input_data         = &lt;br /&gt;
| output_data          = &lt;br /&gt;
| pf_height        = &lt;br /&gt;
| pf_width       = &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Protsenko|Мария Проценко]], [[Участник:ADovganich|Андрей Довганич]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Нечеткий алгоритм C-средних (fuzzy C-means) позволяет разбить имеющееся множество векторов (точек) мощностью p на заданное число нечетких множеств. Предназначен для кластеризации больших наборов данных. Основным достоинством алгоритма является нечеткость при определении объекта в кластер. Благодаря этому становится возможным определить объекты, которые находятся на границе, в кластеры. Из основного достоинства следует и главный недостаток - неопределенность с объектами, удаленными от центров всех кластеров. В остальном ему присущи стандартные проблемы подобного класса алгоритмов: вычислительная сложность, необходимость задания количества кластеров&amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм был разработан J.C. Dunn в 1973 г.&amp;lt;ref&amp;gt; Dunn, J. C. (1973-01-01). &amp;quot;A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters&amp;quot;. Journal of Cybernetics. 3 (3): 32–57. doi:10.1080/01969727308546046. ISSN 0022-0280.&amp;lt;/ref&amp;gt;, усовершенствован J.C. Bezdek в 1981 г.&amp;lt;ref&amp;gt; Bezdek, James C. (1981). Pattern Recognition with Fuzzy Objective Function Algorithms. ISBN 0-306-40671-3.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В общем виде алгоритм можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
1) Инициализировать матрицу принадлежности &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; случайными значениями от 0 до 1;&lt;br /&gt;
&lt;br /&gt;
2) Вычислить центры кластеров &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; используя формулу &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c_{i} = {{\sum_{k = 1}^{K}{m_{ik}^q} * u_{k}} \over {\sum_{k = 1}^{K}{m_{ik}^q}}}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m_{ik}&amp;lt;/math&amp;gt; — коэффициент принадлежности &amp;lt;math&amp;gt;u_{k}&amp;lt;/math&amp;gt; вектора к кластеру &amp;lt;math&amp;gt;c_{i} (1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
3) Вычислить значение решающей функции по формуле &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;. Если значение ниже некоторого порогового или его улучшение по сравнению с предыдущей итерацией меньше определенной величины, то остановить вычисления;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
J(M, c_{1}, c_{2},...c_{c}) = \sum_{i = 1}^{c}{J_{i}} = \sum_{i = 1}^{c}\sum_{k = 1}^{K}{m_{ik}^q}d_{ik}^2 (2)&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Иначе вычислить новые значения матрицы М по формуле &amp;lt;math&amp;gt;(3)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;m_{ik} = {1 \over \sum_{j = 1}^{c}{({{d_{ik}} \over {d_{jk}}})}^{2 \over q-1}}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
5) Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим матрицу &amp;lt;math&amp;gt; M = m_{ik} \in[0,1],\;  i = 1, ..., c, \; k = 1, ..., K &amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;m_{i,k}&amp;lt;/math&amp;gt; - вероятность принадлежности объекта &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; - количество векторов. При этом элементы матрицы удовлетворяют следующим условиям:&lt;br /&gt;
&lt;br /&gt;
- сумма элементов в каждом столбце равна &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
- сумма всех элементов матрицы равно &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Назовем &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; матрицей принадлежности.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; - центры кластеров. Тогда рассмотрим функцию &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; d_{ik} = \left\Vert{u_{k}-c_{i}}\right\| &amp;lt;/math&amp;gt; - Евклидово расстояние между центром кластера и объектом, &amp;lt;math&amp;gt; 1 \le q \le \infty &amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость. Будем минимизировать значение функции &amp;lt;math&amp;gt; J &amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt; (1) &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; (3) &amp;lt;/math&amp;gt; являются необходимым условие достижения минимума этой функцией. Таким образом эти два условия дают нам итерационный процесс, описанный выше.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительным ядром алгоритма являются: &amp;lt;math&amp;gt; (1) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (2) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (3) &amp;lt;/math&amp;gt;. В них производится вычисление новых центров кластеров, значения решающей функции и пересчет элементов матрицы принадлежности.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Макроструктура алгоритма состоит из следующих шагов:&lt;br /&gt;
&lt;br /&gt;
1) Инициализация матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; случайными значениями от 0 до 1;&lt;br /&gt;
&lt;br /&gt;
2) Вычисление центров кластеров; &lt;br /&gt;
&lt;br /&gt;
3) Вычисление значения решающей функции(если оно удовлетворяет условиям останова - завершение вычислений);&lt;br /&gt;
&lt;br /&gt;
4) Вычисление новых элементов матрицы принадлежности;&lt;br /&gt;
&lt;br /&gt;
5) Переход к шагу 2;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации алгоритма на языке С++&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    float ** m;&lt;br /&gt;
    int *c;&lt;br /&gt;
    int number_clusters, number_items;&lt;br /&gt;
    m = gen_random_clusters();//заполним матрицу m случайными значениями от 0 до 1&lt;br /&gt;
    &lt;br /&gt;
    while (true)&lt;br /&gt;
    {&lt;br /&gt;
      //вычисление центров кластеров&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
        {&lt;br /&gt;
            numerator==denumerator=0;&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
            {&lt;br /&gt;
                numerator+=pow(m[i, k], q)*u[k];//u[k]-вектор&lt;br /&gt;
                denumerator+=pow(m[i, k], q);&lt;br /&gt;
            }&lt;br /&gt;
        c[i]= numerator / denumerator;//центры кластеров&lt;br /&gt;
        }&lt;br /&gt;
    &lt;br /&gt;
        j=0;//вычисление решающей функции&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
                j+=pow(m[i, k], q)*pow(dist(c[i], x[k],2);//dist-вычисляет расстояние между заданными векторами&lt;br /&gt;
    &lt;br /&gt;
       if ((abs(j-last_j)&amp;lt;eps1) || (j&amp;lt;eps2)) break;//проверка на необходимость завернешения алгоритма&lt;br /&gt;
       last_j=j;&lt;br /&gt;
     //обновление матрицы m&lt;br /&gt;
       for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
          for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
             {&lt;br /&gt;
               m[i,k]=0&lt;br /&gt;
              for(int j=0; j&amp;lt;number_clusters; j++)&lt;br /&gt;
                  m[i,k]=pow(dist(c[i], x[k]),2/(q-1));&lt;br /&gt;
                 m[i,k]=1/m[i,k];&lt;br /&gt;
              }&lt;br /&gt;
                                       &lt;br /&gt;
    }&lt;br /&gt;
    &amp;lt;/source&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;/div&gt;</summary>
		<author><name>ADovganich</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=8444</id>
		<title>Участник:ADovganich/Нечеткий алгоритм С средних</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=8444"/>
		<updated>2016-10-14T22:54:40Z</updated>

		<summary type="html">&lt;p&gt;ADovganich: /* Макроструктура алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &lt;br /&gt;
| input_data         = &lt;br /&gt;
| output_data          = &lt;br /&gt;
| pf_height        = &lt;br /&gt;
| pf_width       = &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Protsenko|Мария Проценко]], [[Участник:ADovganich|Андрей Довганич]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Нечеткий алгоритм C-средних (fuzzy C-means) позволяет разбить имеющееся множество векторов (точек) мощностью p на заданное число нечетких множеств. Предназначен для кластеризации больших наборов данных. Основным достоинством алгоритма является нечеткость при определении объекта в кластер. Благодаря этому становится возможным определить объекты, которые находятся на границе, в кластеры. Из основного достоинства следует и главный недостаток - неопределенность с объектами, удаленными от центров всех кластеров. В остальном ему присущи стандартные проблемы подобного класса алгоритмов: вычислительная сложность, необходимость задания количества кластеров&amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм был разработан J.C. Dunn в 1973 г.&amp;lt;ref&amp;gt; Dunn, J. C. (1973-01-01). &amp;quot;A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters&amp;quot;. Journal of Cybernetics. 3 (3): 32–57. doi:10.1080/01969727308546046. ISSN 0022-0280.&amp;lt;/ref&amp;gt;, усовершенствован J.C. Bezdek в 1981 г.&amp;lt;ref&amp;gt; Bezdek, James C. (1981). Pattern Recognition with Fuzzy Objective Function Algorithms. ISBN 0-306-40671-3.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В общем виде алгоритм можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
1) Инициализировать матрицу принадлежности &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; случайными значениями от 0 до 1;&lt;br /&gt;
&lt;br /&gt;
2) Вычислить центры кластеров &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; используя формулу &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c_{i} = {{\sum_{k = 1}^{K}{m_{ik}^q} * u_{k}} \over {\sum_{k = 1}^{K}{m_{ik}^q}}}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m_{ik}&amp;lt;/math&amp;gt; — коэффициент принадлежности &amp;lt;math&amp;gt;u_{k}&amp;lt;/math&amp;gt; вектора к кластеру &amp;lt;math&amp;gt;c_{i} (1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
3) Вычислить значение решающей функции по формуле &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;. Если значение ниже некоторого порогового или его улучшение по сравнению с предыдущей итерацией меньше определенной величины, то остановить вычисления;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
J(M, c_{1}, c_{2},...c_{c}) = \sum_{i = 1}^{c}{J_{i}} = \sum_{i = 1}^{c}\sum_{k = 1}^{K}{m_{ik}^q}d_{ik}^2 (2)&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Иначе вычислить новые значения матрицы М по формуле &amp;lt;math&amp;gt;(3)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;m_{ik} = {1 \over \sum_{j = 1}^{c}{({{d_{ik}} \over {d_{jk}}})}^{2 \over q-1}}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
5) Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим матрицу &amp;lt;math&amp;gt; M = m_{ik} \in[0,1],\;  i = 1, ..., c, \; k = 1, ..., K &amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;m_{i,k}&amp;lt;/math&amp;gt; - вероятность принадлежности объекта &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; - количество векторов. При этом элементы матрицы удовлетворяют следующим условиям:&lt;br /&gt;
&lt;br /&gt;
- сумма элементов в каждом столбце равна &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
- сумма всех элементов матрицы равно &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Назовем &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; матрицей принадлежности.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; - центры кластеров. Тогда рассмотрим функцию &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; d_{ik} = \left\Vert{u_{k}-c_{i}}\right\| &amp;lt;/math&amp;gt; - Евклидово расстояние между центром кластера и объектом, &amp;lt;math&amp;gt; 1 \le q \le \infty &amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость. Будем минимизировать значение функции &amp;lt;math&amp;gt; J &amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt; (1) &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; (3) &amp;lt;/math&amp;gt; являются необходимым условие достижения минимума этой функцией. Таким образом эти два условия дают нам итерационный процесс, описанный выше.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительным ядром алгоритма являются: &amp;lt;math&amp;gt; (1) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (2) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (3) &amp;lt;/math&amp;gt;. В них производится вычисление новых центров кластеров, значения решающей функции и пересчет элементов матрицы принадлежности.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Макроструктура алгоритма состоит из следующих шагов:&lt;br /&gt;
&lt;br /&gt;
1) Инициализация матрицы &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; случайными значениями от 0 до 1;&lt;br /&gt;
&lt;br /&gt;
2) Вычисление центров кластеров; &lt;br /&gt;
&lt;br /&gt;
3) Вычисление значения решающей функции(если оно удовлетворяет условиям останова - завершение вычислений);&lt;br /&gt;
&lt;br /&gt;
4) Вычисление новых элементов матрицы принадлежности&lt;br /&gt;
&lt;br /&gt;
5) Переход к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Пример реализации алгоритма на языке С++&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
    float ** m;&lt;br /&gt;
    int *c;&lt;br /&gt;
    int number_clusters, number_items;&lt;br /&gt;
    m = gen_random_clusters();//заполним матрицу m случайными значениями от 0 до 1&lt;br /&gt;
    &lt;br /&gt;
    while (true)&lt;br /&gt;
    {&lt;br /&gt;
      //вычисление центров кластеров&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
        {&lt;br /&gt;
            numerator==denumerator=0;&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
            {&lt;br /&gt;
                numerator+=pow(m[i, k], q)*u[k];//u[k]-вектор&lt;br /&gt;
                denumerator+=pow(m[i, k], q);&lt;br /&gt;
            }&lt;br /&gt;
        c[i]= numerator / denumerator;//центры кластеров&lt;br /&gt;
        }&lt;br /&gt;
    &lt;br /&gt;
        j=0;//вычисление решающей функции&lt;br /&gt;
        for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
            for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
                j+=pow(m[i, k], q)*pow(dist(c[i], x[k],2);//dist-вычисляет расстояние между заданными векторами&lt;br /&gt;
    &lt;br /&gt;
       if ((abs(j-last_j)&amp;lt;eps1) || (j&amp;lt;eps2)) break;//проверка на необходимость завернешения алгоритма&lt;br /&gt;
       last_j=j;&lt;br /&gt;
     //обновление матрицы m&lt;br /&gt;
       for (int i=0; i&amp;lt;number_clusters; i++)&lt;br /&gt;
          for (int k=0; k&amp;lt;number_items; k++)&lt;br /&gt;
             {&lt;br /&gt;
               m[i,k]=0&lt;br /&gt;
              for(int j=0; j&amp;lt;number_clusters; j++)&lt;br /&gt;
                  m[i,k]=pow(dist(c[i], x[k]),2/(q-1));&lt;br /&gt;
                 m[i,k]=1/m[i,k];&lt;br /&gt;
              }&lt;br /&gt;
                                       &lt;br /&gt;
    }&lt;br /&gt;
    &amp;lt;/source&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;/div&gt;</summary>
		<author><name>ADovganich</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=8421</id>
		<title>Участник:ADovganich/Нечеткий алгоритм С средних</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=8421"/>
		<updated>2016-10-14T22:36:49Z</updated>

		<summary type="html">&lt;p&gt;ADovganich: /* Математическое описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &lt;br /&gt;
| input_data         = &lt;br /&gt;
| output_data          = &lt;br /&gt;
| pf_height        = &lt;br /&gt;
| pf_width       = &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Protsenko|Мария Проценко]], [[Участник:ADovganich|Андрей Довганич]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Нечеткий алгоритм C-средних (fuzzy C-means) позволяет разбить имеющееся множество векторов (точек) мощностью p на заданное число нечетких множеств. Предназначен для кластеризации больших наборов данных. Основным достоинством алгоритма является нечеткость при определении объекта в кластер. Благодаря этому становится возможным определить объекты, которые находятся на границе, в кластеры. Из основного достоинства следует и главный недостаток - неопределенность с объектами, удаленными от центров всех кластеров. В остальном ему присущи стандартные проблемы подобного класса алгоритмов: вычислительная сложность, необходимость задания количества кластеров&amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм был разработан J.C. Dunn в 1973 г.&amp;lt;ref&amp;gt; Dunn, J. C. (1973-01-01). &amp;quot;A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters&amp;quot;. Journal of Cybernetics. 3 (3): 32–57. doi:10.1080/01969727308546046. ISSN 0022-0280.&amp;lt;/ref&amp;gt;, усовершенствован J.C. Bezdek в 1981 г.&amp;lt;ref&amp;gt; Bezdek, James C. (1981). Pattern Recognition with Fuzzy Objective Function Algorithms. ISBN 0-306-40671-3.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В общем виде алгоритм можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
1) Инициализировать матрицу принадлежности &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; случайными значениями от 0 до 1;&lt;br /&gt;
&lt;br /&gt;
2) Вычислить центры кластеров &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; используя формулу &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c_{i} = {{\sum_{k = 1}^{K}{m_{ik}^q} * u_{k}} \over {\sum_{k = 1}^{K}{m_{ik}^q}}}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m_{ik}&amp;lt;/math&amp;gt; — коэффициент принадлежности &amp;lt;math&amp;gt;u_{k}&amp;lt;/math&amp;gt; вектора к кластеру &amp;lt;math&amp;gt;c_{i} (1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
3) Вычислить значение решающей функции по формуле &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;. Если значение ниже некоторого порогового или его улучшение по сравнению с предыдущей итерацией меньше определенной величины, то остановить вычисления;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
J(M, c_{1}, c_{2},...c_{c}) = \sum_{i = 1}^{c}{J_{i}} = \sum_{i = 1}^{c}\sum_{k = 1}^{K}{m_{ik}^q}d_{ik}^2 (2)&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Иначе вычислить новые значения матрицы М по формуле &amp;lt;math&amp;gt;(3)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;m_{ik} = {1 \over \sum_{j = 1}^{c}{({{d_{ik}} \over {d_{jk}}})}^{2 \over q-1}}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
5) Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим матрицу &amp;lt;math&amp;gt; M = m_{ik} \in[0,1],\;  i = 1, ..., c, \; k = 1, ..., K &amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;m_{i,k}&amp;lt;/math&amp;gt; - вероятность принадлежности объекта &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; - количество векторов. При этом элементы матрицы удовлетворяют следующим условиям:&lt;br /&gt;
&lt;br /&gt;
- сумма элементов в каждом столбце равна &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
- сумма всех элементов матрицы равно &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Назовем &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; матрицей принадлежности.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; - центры кластеров. Тогда рассмотрим функцию &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; d_{ik} = \left\Vert{u_{k}-c_{i}}\right\| &amp;lt;/math&amp;gt; - Евклидово расстояние между центром кластера и объектом, &amp;lt;math&amp;gt; 1 \le q \le \infty &amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость. Будем минимизировать значение функции &amp;lt;math&amp;gt; J &amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt; (1) &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; (3) &amp;lt;/math&amp;gt; являются необходимым условие достижения минимума этой функцией. Таким образом эти два условия дают нам итерационный процесс, описанный выше.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительным ядром алгоритма являются: &amp;lt;math&amp;gt; (1) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (2) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (3) &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>ADovganich</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=8416</id>
		<title>Участник:ADovganich/Нечеткий алгоритм С средних</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=8416"/>
		<updated>2016-10-14T22:31:29Z</updated>

		<summary type="html">&lt;p&gt;ADovganich: /* Вычислительное ядро алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &lt;br /&gt;
| input_data         = &lt;br /&gt;
| output_data          = &lt;br /&gt;
| pf_height        = &lt;br /&gt;
| pf_width       = &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Protsenko|Мария Проценко]], [[Участник:ADovganich|Андрей Довганич]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Нечеткий алгоритм C-средних (fuzzy C-means) позволяет разбить имеющееся множество векторов (точек) мощностью p на заданное число нечетких множеств. Предназначен для кластеризации больших наборов данных. Основным достоинством алгоритма является нечеткость при определении объекта в кластер. Благодаря этому становится возможным определить объекты, которые находятся на границе, в кластеры. Из основного достоинства следует и главный недостаток - неопределенность с объектами, удаленными от центров всех кластеров. В остальном ему присущи стандартные проблемы подобного класса алгоритмов: вычислительная сложность, необходимость задания количества кластеров&amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм был разработан J.C. Dunn в 1973 г.&amp;lt;ref&amp;gt; Dunn, J. C. (1973-01-01). &amp;quot;A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters&amp;quot;. Journal of Cybernetics. 3 (3): 32–57. doi:10.1080/01969727308546046. ISSN 0022-0280.&amp;lt;/ref&amp;gt;, усовершенствован J.C. Bezdek в 1981 г.&amp;lt;ref&amp;gt; Bezdek, James C. (1981). Pattern Recognition with Fuzzy Objective Function Algorithms. ISBN 0-306-40671-3.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В общем виде алгоритм можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
1) Инициализировать матрицу принадлежности &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; случайными значениями от 0 до 1;&lt;br /&gt;
&lt;br /&gt;
2) Вычислить центры кластеров &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; используя формулу &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c_{i} = {{\sum_{k = 1}^{K}{m_{ik}^q} * u_{k}} \over {\sum_{k = 1}^{K}{m_{ik}^q}}}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m_{ik}&amp;lt;/math&amp;gt; — коэффициент принадлежности &amp;lt;math&amp;gt;u_{k}&amp;lt;/math&amp;gt; вектора к кластеру &amp;lt;math&amp;gt;c_{i} (1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
3) Вычислить значение решающей функции по формуле &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;. Если значение ниже некоторого порогового или его улучшение по сравнению с предыдущей итерацией меньше определенной величины, то остановить вычисления;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
J(M, c_{1}, c_{2},...c_{c}) = \sum_{i = 1}^{c}{J_{i}} = \sum_{i = 1}^{c}\sum_{k = 1}^{K}{m_{ik}^q}d_{ik}^2 (2)&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Иначе вычислить новые значения матрицы М по формуле &amp;lt;math&amp;gt;(3)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;m_{ik} = {1 \over \sum_{j = 1}^{c}{({{d_{ik}} \over {d_{jk}}})}^{2 \over q-1}}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
5) Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим матрицу &amp;lt;math&amp;gt; M = m_{ik} \in[0,1],\;  i = 1, ..., c, \; k = 1, ..., K &amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;m_{i,k}&amp;lt;/math&amp;gt; - вероятность принадлежности объекта &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; - количество векторов. При этом элементы матрицы удовлетворяют следующим условиям:&lt;br /&gt;
&lt;br /&gt;
- сумма элементов в каждом столбце равна &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
- сумма всех элементов матрицы равно &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Назовем &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; матрицей принадлежности.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; - центры кластеров. Тогда рассмотрим функцию &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; d_{i,k} = \left\Vert{u_{k}-c_{i}}\right\| &amp;lt;/math&amp;gt; - Евклидово расстояние между центром кластера и объектом, &amp;lt;math&amp;gt; 1 \le q \le \infty &amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость. Будем минимизировать значение функции &amp;lt;math&amp;gt; J &amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt; (1) &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; (3) &amp;lt;/math&amp;gt; являются необходимым условие достижения минимума этой функцией. Таким образом эти два условия дают нам итерационный процесс, описанный выше.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительным ядром алгоритма являются: &amp;lt;math&amp;gt; (1) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (2) &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; (3) &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>ADovganich</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=8407</id>
		<title>Участник:ADovganich/Нечеткий алгоритм С средних</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=8407"/>
		<updated>2016-10-14T22:26:17Z</updated>

		<summary type="html">&lt;p&gt;ADovganich: /* Общее описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &lt;br /&gt;
| input_data         = &lt;br /&gt;
| output_data          = &lt;br /&gt;
| pf_height        = &lt;br /&gt;
| pf_width       = &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Protsenko|Мария Проценко]], [[Участник:ADovganich|Андрей Довганич]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Нечеткий алгоритм C-средних (fuzzy C-means) позволяет разбить имеющееся множество векторов (точек) мощностью p на заданное число нечетких множеств. Предназначен для кластеризации больших наборов данных. Основным достоинством алгоритма является нечеткость при определении объекта в кластер. Благодаря этому становится возможным определить объекты, которые находятся на границе, в кластеры. Из основного достоинства следует и главный недостаток - неопределенность с объектами, удаленными от центров всех кластеров. В остальном ему присущи стандартные проблемы подобного класса алгоритмов: вычислительная сложность, необходимость задания количества кластеров&amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм был разработан J.C. Dunn в 1973 г.&amp;lt;ref&amp;gt; Dunn, J. C. (1973-01-01). &amp;quot;A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters&amp;quot;. Journal of Cybernetics. 3 (3): 32–57. doi:10.1080/01969727308546046. ISSN 0022-0280.&amp;lt;/ref&amp;gt;, усовершенствован J.C. Bezdek в 1981 г.&amp;lt;ref&amp;gt; Bezdek, James C. (1981). Pattern Recognition with Fuzzy Objective Function Algorithms. ISBN 0-306-40671-3.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В общем виде алгоритм можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
1) Инициализировать матрицу принадлежности &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; случайными значениями от 0 до 1;&lt;br /&gt;
&lt;br /&gt;
2) Вычислить центры кластеров &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; используя формулу &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c_{i} = {{\sum_{k = 1}^{K}{m_{ik}^q} * u_{k}} \over {\sum_{k = 1}^{K}{m_{ik}^q}}}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m_{ik}&amp;lt;/math&amp;gt; — коэффициент принадлежности &amp;lt;math&amp;gt;u_{k}&amp;lt;/math&amp;gt; вектора к кластеру &amp;lt;math&amp;gt;c_{i} (1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
3) Вычислить значение решающей функции по формуле &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;. Если значение ниже некоторого порогового или его улучшение по сравнению с предыдущей итерацией меньше определенной величины, то остановить вычисления;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
J(M, c_{1}, c_{2},...c_{c}) = \sum_{i = 1}^{c}{J_{i}} = \sum_{i = 1}^{c}\sum_{k = 1}^{K}{m_{ik}^q}d_{ik}^2 (2)&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Иначе вычислить новые значения матрицы М по формуле &amp;lt;math&amp;gt;(3)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;m_{ik} = {1 \over \sum_{j = 1}^{c}{({{d_{ik}} \over {d_{jk}}})}^{2 \over q-1}}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
5) Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим матрицу &amp;lt;math&amp;gt; M = m_{ik} \in[0,1],\;  i = 1, ..., c, \; k = 1, ..., K &amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;m_{i,k}&amp;lt;/math&amp;gt; - вероятность принадлежности объекта &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; - количество векторов. При этом элементы матрицы удовлетворяют следующим условиям:&lt;br /&gt;
&lt;br /&gt;
- сумма элементов в каждом столбце равна &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
- сумма всех элементов матрицы равно &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Назовем &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; матрицей принадлежности.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; - центры кластеров. Тогда рассмотрим функцию &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; d_{i,k} = \left\Vert{u_{k}-c_{i}}\right\| &amp;lt;/math&amp;gt; - Евклидово расстояние между центром кластера и объектом, &amp;lt;math&amp;gt; 1 \le q \le \infty &amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость. Будем минимизировать значение функции &amp;lt;math&amp;gt; J &amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt; (1) &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; (3) &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>ADovganich</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=8397</id>
		<title>Участник:ADovganich/Нечеткий алгоритм С средних</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=8397"/>
		<updated>2016-10-14T22:19:46Z</updated>

		<summary type="html">&lt;p&gt;ADovganich: /* Математическое описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &lt;br /&gt;
| input_data         = &lt;br /&gt;
| output_data          = &lt;br /&gt;
| pf_height        = &lt;br /&gt;
| pf_width       = &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Protsenko|Мария Проценко]], [[Участник:ADovganich|Андрей Довганич]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Нечеткий алгоритм C-средних (fuzzy C-means) позволяет разбить имеющееся множество векторов (точек) мощностью p на заданное число нечетких множеств. Предназначен для кластеризации больших наборов данных. Основным достоинством алгоритма является нечеткость при определении объекта в кластер. Благодаря этому становится возможным определить объекты, которые находятся на границе, в кластеры. Из основного достоинства следует и главный недостаток - неопределенность с объектами, удаленными от центров всех кластеров. В остальном ему присущи стандартные проблемы подобного класса алгоритмов: вычислительная сложность, необходимость задания количества кластеров&amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм был разработан J.C. Dunn в 1973 г.&amp;lt;ref&amp;gt; Dunn, J. C. (1973-01-01). &amp;quot;A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters&amp;quot;. Journal of Cybernetics. 3 (3): 32–57. doi:10.1080/01969727308546046. ISSN 0022-0280.&amp;lt;/ref&amp;gt;, усовершенствован J.C. Bezdek в 1981 г.&amp;lt;ref&amp;gt; Bezdek, James C. (1981). Pattern Recognition with Fuzzy Objective Function Algorithms. ISBN 0-306-40671-3.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В общем виде алгоритм можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
1) Инициализировать матрицу принадлежности M случайными значениями от 0 до 1;&lt;br /&gt;
&lt;br /&gt;
2) Вычислить центры кластеров &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; используя формулу &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c_{i} = {{\sum_{k = 1}^{K}{m_{ik}^q} * u_{k}} \over {\sum_{k = 1}^{K}{m_{ik}^q}}}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m_{ik}&amp;lt;/math&amp;gt; — коэффициент принадлежности &amp;lt;math&amp;gt;u_{k}&amp;lt;/math&amp;gt; вектора к кластеру &amp;lt;math&amp;gt;c_{i} (1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
3) Вычислить значение решающей функции по формуле &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;. Если значение ниже некоторого порогового или его улучшение по сравнению с предыдущей итерацией меньше определенной величины, то остановить вычисления;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
J(M, c_{1}, c_{2},...c_{c}) = \sum_{i = 1}^{c}{J_{i}} = \sum_{i = 1}^{c}\sum_{k = 1}^{K}{m_{ik}^q}d_{ik}^2 (2)&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Иначе вычислить новые значения матрицы М по формуле &amp;lt;math&amp;gt;(3)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;m_{ik} = {1 \over \sum_{j = 1}^{c}{({{d_{ik}} \over {d_{jk}}})}^{2 \over q-1}}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
5) Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим матрицу &amp;lt;math&amp;gt; M = m_{ik} \in[0,1],\;  i = 1, ..., c, \; k = 1, ..., K &amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;m_{i,k}&amp;lt;/math&amp;gt; - вероятность принадлежности объекта &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; - количество векторов. При этом элементы матрицы удовлетворяют следующим условиям:&lt;br /&gt;
&lt;br /&gt;
- сумма элементов в каждом столбце равна &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
- сумма всех элементов матрицы равно &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Назовем &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt; матрицей принадлежности.&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; - центры кластеров. Тогда рассмотрим функцию &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; d_{i,k} = \left\Vert{u_{k}-c_{i}}\right\| &amp;lt;/math&amp;gt; - Евклидово расстояние между центром кластера и объектом, &amp;lt;math&amp;gt; 1 \le q \le \infty &amp;lt;/math&amp;gt; - экспоненциальный весовой коэффициент, характеризующий нечеткость. Будем минимизировать значение функции &amp;lt;math&amp;gt; J &amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt; (1) &amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; (3) &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>ADovganich</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=8363</id>
		<title>Участник:ADovganich/Нечеткий алгоритм С средних</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=8363"/>
		<updated>2016-10-14T22:02:40Z</updated>

		<summary type="html">&lt;p&gt;ADovganich: /* Общее описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &lt;br /&gt;
| input_data         = &lt;br /&gt;
| output_data          = &lt;br /&gt;
| pf_height        = &lt;br /&gt;
| pf_width       = &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Protsenko|Мария Проценко]], [[Участник:ADovganich|Андрей Довганич]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Нечеткий алгоритм C-средних (fuzzy C-means) позволяет разбить имеющееся множество векторов (точек) мощностью p на заданное число нечетких множеств. Предназначен для кластеризации больших наборов данных. Основным достоинством алгоритма является нечеткость при определении объекта в кластер. Благодаря этому становится возможным определить объекты, которые находятся на границе, в кластеры. Из основного достоинства следует и главный недостаток - неопределенность с объектами, удаленными от центров всех кластеров. В остальном ему присущи стандартные проблемы подобного класса алгоритмов: вычислительная сложность, необходимость задания количества кластеров&amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм был разработан J.C. Dunn в 1973 г.&amp;lt;ref&amp;gt; Dunn, J. C. (1973-01-01). &amp;quot;A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters&amp;quot;. Journal of Cybernetics. 3 (3): 32–57. doi:10.1080/01969727308546046. ISSN 0022-0280.&amp;lt;/ref&amp;gt;, усовершенствован J.C. Bezdek в 1981 г.&amp;lt;ref&amp;gt; Bezdek, James C. (1981). Pattern Recognition with Fuzzy Objective Function Algorithms. ISBN 0-306-40671-3.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В общем виде алгоритм можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
1) Инициализировать матрицу принадлежности M случайными значениями от 0 до 1;&lt;br /&gt;
&lt;br /&gt;
2) Вычислить центры кластеров &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; используя формулу &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c_{i} = {{\sum_{k = 1}^{K}{m_{ik}^q} * u_{k}} \over {\sum_{k = 1}^{K}{m_{ik}^q}}}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m_{ik}&amp;lt;/math&amp;gt; — коэффициент принадлежности &amp;lt;math&amp;gt;u_{k}&amp;lt;/math&amp;gt; вектора к кластеру &amp;lt;math&amp;gt;c_{i} (1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
3) Вычислить значение решающей функции по формуле &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;. Если значение ниже некоторого порогового или его улучшение по сравнению с предыдущей итерацией меньше определенной величины, то остановить вычисления;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
J(M, c_{1}, c_{2},...c_{c}) = \sum_{i = 1}^{c}{J_{i}} = \sum_{i = 1}^{c}\sum_{k = 1}^{K}{m_{ik}^q}d_{ik}^2 (2)&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Иначе вычислить новые значения матрицы М по формуле &amp;lt;math&amp;gt;(3)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;m_{ik} = {1 \over \sum_{j = 1}^{c}{({{d_{ik}} \over {d_{jk}}})}^{2 \over q-1}}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
5) Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим матрицу &amp;lt;math&amp;gt; M = m_{ik} \in[0,1],\;  i = 1, ..., c, \; k = 1, ..., K &amp;lt;/math&amp;gt;. Назовем её матрицей принадлежности. &amp;lt;math&amp;gt;m_{i,k}&amp;lt;/math&amp;gt; - вероятность принадлежности объекта &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; - количество векторов. При этом элементы матрицы удовлетворяют следующим условиям:&lt;br /&gt;
&lt;br /&gt;
- сумма элементов в каждом столбце равна &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
- сумма всех элементов матрицы равно &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; - центры кластеров. Тогда рассмотрим функцию (2), где &amp;lt;math&amp;gt; d_{i,k} = \left\Vert{u_{k}-c_{i}}\right\| &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>ADovganich</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=7860</id>
		<title>Участник:ADovganich/Нечеткий алгоритм С средних</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=7860"/>
		<updated>2016-10-14T17:54:18Z</updated>

		<summary type="html">&lt;p&gt;ADovganich: /* Математическое описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &lt;br /&gt;
| input_data         = &lt;br /&gt;
| output_data          = &lt;br /&gt;
| pf_height        = &lt;br /&gt;
| pf_width       = &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Protsenko|Мария Проценко]], [[Участник:ADovganich|Андрей Довганич]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Нечеткий алгоритм C-средних (fuzzy C-means) позволяет разбить имеющееся множество векторов (точек) мощностью p на заданное число нечетких множеств. Предназначен для кластеризации больших наборов данных. Основным достоинством алгоритма является нечеткость при определении объекта в кластер. Благодаря этому становится возможным определить объекты, которые находятся на границе, в кластеры. Из основного достоинства следует и главный недостаток - неопределенность с объектами, удаленными от центров всех кластеров. В остальном ему присущи стандартные проблемы подобного класса алгоритмов: вычислительная сложность, необходимость задания количества кластеров&amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм был разработан J.C. Dunn в 1973 г.&amp;lt;ref&amp;gt; Dunn, J. C. (1973-01-01). &amp;quot;A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters&amp;quot;. Journal of Cybernetics. 3 (3): 32–57. doi:10.1080/01969727308546046. ISSN 0022-0280.&amp;lt;/ref&amp;gt;, усовершенствован J.C. Bezdek в 1981 г.&amp;lt;ref&amp;gt; Bezdek, James C. (1981). Pattern Recognition with Fuzzy Objective Function Algorithms. ISBN 0-306-40671-3.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В общем виде алгоритм можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
1) Инициализировать матрицу принадлежности M случайными значениями от 0 до 1;&lt;br /&gt;
&lt;br /&gt;
2) Вычислить центры кластеров &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; используя формулу &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c_{i} = {{\sum_{k = 1}^{K}{m_{i,k}^q} * u_{k}} \over {\sum_{k = 1}^{K}{m_{i,k}^q}}}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m_{i,k}&amp;lt;/math&amp;gt; — коэффициент принадлежности &amp;lt;math&amp;gt;u_{k}&amp;lt;/math&amp;gt; вектора к кластеру &amp;lt;math&amp;gt;c_{i} (1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
3) Вычислить значение решающей функции по формуле &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;. Если значение ниже некоторого порогового или его улучшение по сравнению с предыдущей итерацией меньше определенной величины, то остановить вычисления;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
J(M, c_{1}, c_{2},...c_{c}) = \sum_{i = 1}^{c}{J_{i}} = \sum_{i = 1}^{c}\sum_{k = 1}^{K}{m_{i,k}^q}d_{i,k}^2 (2)&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Иначе вычислить новые значения матрицы М по формуле &amp;lt;math&amp;gt;(3)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;m_{i,k} = {1 \over \sum_{j = 1}^{c}{({{d_{i,k}} \over {d_{j,k}}})}^{2 \over q-1}}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
5) Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассмотрим матрицу &amp;lt;math&amp;gt; M = m_{ik} \in[0,1],\;  i = 1, ..., c, \; k = 1, ..., K &amp;lt;/math&amp;gt;. Назовем её матрицей принадлежности. &amp;lt;math&amp;gt;m_{i,k}&amp;lt;/math&amp;gt; - вероятность принадлежности объекта &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;; &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; - количество векторов. При этом элементы матрицы удовлетворяют следующим условиям:&lt;br /&gt;
&lt;br /&gt;
- сумма элементов в каждом столбце равна &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
- сумма всех элементов матрицы равно &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; - центры кластеров. Тогда рассмотрим функцию (2), где &amp;lt;math&amp;gt; d_{i,k} = \left\Vert{u_{k}-c_{i}}\right\| &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>ADovganich</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=6672</id>
		<title>Участник:ADovganich/Нечеткий алгоритм С средних</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=6672"/>
		<updated>2016-10-13T17:33:24Z</updated>

		<summary type="html">&lt;p&gt;ADovganich: /* Общее описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &lt;br /&gt;
| input_data         = &lt;br /&gt;
| output_data          = &lt;br /&gt;
| pf_height        = &lt;br /&gt;
| pf_width       = &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Protsenko|Мария Проценко]], [[Участник:ADovganich|Андрей Довганич]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Нечеткий алгоритм C-средних (fuzzy C-means) позволяет разбить имеющееся множество векторов (точек) мощностью p на заданное число нечетких множеств. Предназначен для кластеризации больших наборов данных. Основным достоинством алгоритма является нечеткость при определении объекта в кластер. Благодаря этому становится возможным определить объекты, которые находятся на границе, в кластеры. Из основного достоинства следует и главный недостаток - неопределенность с объектами, удаленными от центров всех кластеров. В остальном ему присущи стандартные проблемы подобного класса алгоритмов: вычислительная сложность, необходимость задания количества кластеров&amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм был разработан J.C. Dunn в 1973 г.&amp;lt;ref&amp;gt; Dunn, J. C. (1973-01-01). &amp;quot;A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters&amp;quot;. Journal of Cybernetics. 3 (3): 32–57. doi:10.1080/01969727308546046. ISSN 0022-0280.&amp;lt;/ref&amp;gt;, усовершенствован J.C. Bezdek в 1981 г.&amp;lt;ref&amp;gt; Bezdek, James C. (1981). Pattern Recognition with Fuzzy Objective Function Algorithms. ISBN 0-306-40671-3.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В общем виде алгоритм можно записать следующим образом:&lt;br /&gt;
&lt;br /&gt;
1) Инициализировать матрицу принадлежности M случайными значениями от 0 до 1;&lt;br /&gt;
&lt;br /&gt;
2) Вычислить центры кластеров &amp;lt;math&amp;gt;c_{i} (i = 1,2,...c)&amp;lt;/math&amp;gt; используя формулу &amp;lt;math&amp;gt;(1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c_{i} = {{\sum_{k = 1}^{K}{m_{i,k}^q} * u_{k}} \over {\sum_{k = 1}^{K}{m_{i,k}^q}}}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m_{i,k}&amp;lt;/math&amp;gt; — коэффициент принадлежности &amp;lt;math&amp;gt;u_{k}&amp;lt;/math&amp;gt; вектора к кластеру &amp;lt;math&amp;gt;c_{i} (1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
3) Вычислить значение решающей функции по формуле &amp;lt;math&amp;gt;(2)&amp;lt;/math&amp;gt;. Если значение ниже некоторого порогового или его улучшение по сравнению с предыдущей итерацией меньше определенной величины, то остановить вычисления;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
J(M, c_{1}, c_{2},...c_{c}) = \sum_{i = 1}^{c}{J_{i}} = \sum_{i = 1}^{c}\sum_{k = 1}^{K}{m_{i,k}^q}d_{i,k}^2 (2)&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
4) Иначе вычислить новые значения матрицы М по формуле &amp;lt;math&amp;gt;(3)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;m_{i,k} = {1 \over \sum_{j = 1}^{c}{({{d_{i,k}} \over {d_{j,k}}})}^{2 \over q-1}}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
5) Перейти к шагу 2&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;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>ADovganich</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:ADovganich&amp;diff=6469</id>
		<title>Участник:ADovganich</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:ADovganich&amp;diff=6469"/>
		<updated>2016-10-13T13:18:17Z</updated>

		<summary type="html">&lt;p&gt;ADovganich: Создана пустая страница&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>ADovganich</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=6422</id>
		<title>Участник:ADovganich/Нечеткий алгоритм С средних</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:ADovganich/%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_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=6422"/>
		<updated>2016-10-13T12:21:13Z</updated>

		<summary type="html">&lt;p&gt;ADovganich: Новая страница: «{{algorithm | name              = Нечеткий алгоритм C средних | serial_complexity =  | input_data         =  | output_data          =  | pf…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних&lt;br /&gt;
| serial_complexity = &lt;br /&gt;
| input_data         = &lt;br /&gt;
| output_data          = &lt;br /&gt;
| pf_height        = &lt;br /&gt;
| pf_width       = &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы : [[Участник:Protsenko|Мария Проценко]], [[Участник:ADovganich|Андрей Довганич]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;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>ADovganich</name></author>
	</entry>
</feed>