<?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=Coctic</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=Coctic"/>
	<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/Coctic"/>
	<updated>2026-10-22T18:15:35Z</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:%D0%A8%D0%B8%D1%88%D0%BA%D0%BE%D0%B2_%D0%98%D0%BB%D1%8C%D1%8F_%D0%A1%D0%B5%D1%80%D0%B3%D0%B5%D0%B5%D0%B2%D0%B8%D1%87/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_HCM_(Hard_C_%E2%80%93_Means)&amp;diff=21055</id>
		<title>Участник:Шишков Илья Сергеевич/Алгоритм HCM (Hard C – Means)</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:%D0%A8%D0%B8%D1%88%D0%BA%D0%BE%D0%B2_%D0%98%D0%BB%D1%8C%D1%8F_%D0%A1%D0%B5%D1%80%D0%B3%D0%B5%D0%B5%D0%B2%D0%B8%D1%87/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_HCM_(Hard_C_%E2%80%93_Means)&amp;diff=21055"/>
		<updated>2016-12-16T13:04:12Z</updated>

		<summary type="html">&lt;p&gt;Coctic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|{{REVISIONUSER}}}}&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Алгоритм HCM (Hard C – Means)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(ncK)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(cK)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;O(nK)&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;O(c(K+n))&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Основные авторы описания: [[Участник:Шишков_Илья_Сергеевич|Илья Шишков]] (1.1-1.4, 2.7, 2.4), [[Участник:Темербекова_Гульгайша|Гульгайша Темербекова]] (1.5-1.10, 3, 2.4)&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Алгоритм HCM (Строгий алгоритм С-средних) был предложен группой исследователей(Jang, Sun and Mizutani) в 1997 и относится к классу алгоритмов со строгой кластеризаций. &lt;br /&gt;
&lt;br /&gt;
Кластеризацией называется подход к описанию данных, в котором наиболее схожие данные объединяются в группы(кластеры). Кластеризация является распространенным подходом для анализа данных и используется во многих сферах научной деятельности, таких как машинное обучение, анализ данных, распознавание шаблонов, анализ изображений и биоинформатика.&lt;br /&gt;
&lt;br /&gt;
Кластеризация представляет собой комбинирование рассматриваемых объектов так, чтобы каждая группа объектов обладала схожим свойством. В общем случае кластеризация характеризуются следующими критериями:&lt;br /&gt;
- Каждая группа или кластер однородны; объекты, принадлежащие одной группе имеют схожие свойства;&lt;br /&gt;
- Каждая группа или кластер отличаются от других кластеров т.е. объекты, принадлежащие одному кластеру, должны отличатся от объектов других кластеров&lt;br /&gt;
&lt;br /&gt;
В строгой кластеризации наборы данных разделяются на кластеры однозначно. Каждый набор данных может относится только к одному кластеру. &lt;br /&gt;
Строгой кластеризации характеризуется следующими свойствами:&lt;br /&gt;
- Используется для классификации данных в однозначные наборы&lt;br /&gt;
- Каждый набор данных принадлежит только одному кластеру&lt;br /&gt;
- Кластеры также называют разделами&lt;br /&gt;
- Результатом работы кластерного алгоритма является матрица соответствия которая показывает, к какому кластеру принадлежит каждый набор данных&lt;br /&gt;
&lt;br /&gt;
В этом кластерном алгоритме не допускается частичное отношение к кластеру (как в FCM). HCM предназначен для классификации входных наборов в строгом смысле. В строгом алгоритме С-средних данные классифицируются по кластерам однозначно, т.е. при определенном заранее критерии, каждый элемент данных может принадлежать одному и только одному кластеру. &lt;br /&gt;
&lt;br /&gt;
Алгоритм HCM является итеративным и состоит из нескольких шагов: &lt;br /&gt;
&lt;br /&gt;
1.&#039;&#039;&#039;Инициализация: &#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Случайным образом определяются C векторов - центров кластеров&lt;br /&gt;
&lt;br /&gt;
2. &#039;&#039;&#039;Расчет рядовой матрицы:&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
В процессе расчета рядовой матрицы каждый вектор сравнивается с ближайшим кластерным центром&lt;br /&gt;
&lt;br /&gt;
3. &#039;&#039;&#039;Расчет оценочной функции:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Проверка условия, при котором алгоритм завершает работу и вывод результата в этом случае&lt;br /&gt;
&lt;br /&gt;
4. &#039;&#039;&#039;Переопределение кластерных центров&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Пункты 2-4 выполняются до тех пор, пока в пункте 3 проверка не станет успешной.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма &amp;lt;ref&amp;gt;Arabinda Panda &amp;amp; Satchidananda Dehuri. Hard C-means Clustering Algorithm in Gene Expression Data // International Journal on Advanced Computer Theory and Engineering, ISSN-PRINT: 2319-2526. - 2013. - v. 2. - p. 35-39 [http://www.irdindia.in/journal_ijacte/pdf/vol2_iss1/8.pdf]&amp;lt;/ref&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Обозначения&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;U&amp;lt;/math&amp;gt; - наборы данных&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;u_{i}&amp;lt;/math&amp;gt; - i-ый набор из &amp;lt;math&amp;gt;U&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;u&amp;lt;/math&amp;gt; - любой набор из &amp;lt;math&amp;gt;U&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; - количество наборов в &amp;lt;math&amp;gt;U&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c_{j}&amp;lt;/math&amp;gt; - j-ый кластер&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c_{j}&amp;lt;/math&amp;gt; - j-ый кластерный центр&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c^*_{j}&amp;lt;/math&amp;gt; - j-ый кластерный центр после обновления&lt;br /&gt;
&lt;br /&gt;
Выходные данные: &lt;br /&gt;
&amp;lt;math&amp;gt;c^*_{1}, c^*_{2}, ... c^*_{c}, M&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Объектная функция:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;J=\sum_{j = 1}^{c} \sum_{u_{i} \in C_{j}}^{} \|u_{i}-c_{j}\|^2,  j \in 1,2, ... c, i={1,2, ...K}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 1&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Из входного набора &amp;lt;math&amp;gt;u_{1},u_{2}, ... u_{n}&amp;lt;/math&amp;gt; выбираются &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; начальных кластерных центра &amp;lt;math&amp;gt; c_{1},c_{2},...,c_{c}&amp;lt;/math&amp;gt;либо случайным образом, либо с использованием заранее определенного алгоритма&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 2&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Рассчитывается рядовая матрица &amp;lt;math&amp;gt; M=\|m_{ik}\|&amp;lt;/math&amp;gt; каждый элемент которой вычисляется по следующей формуле: &lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ik} = \begin{cases}&lt;br /&gt;
1, &amp;amp; \|u_k-c_i\|^2 \leqslant \|u_k-c_j\|^2 \;\; \text{for all } i \neq j; \;\; (i,j=1,2,\ldots,c; \; k = 1,2,\ldots,K)\\&lt;br /&gt;
0, &amp;amp; \text{other}.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 3&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Рассчитывается объектная функция J. На этом этапе может быть инициировано завершение алгоритма в случае если значение объектной функции незначительно изменилось относительно предыдущей итерации или достигло ожидаемого значения. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 4&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Рассчитываются новые кластерные центры по следующей формуле: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; c^*_{j} = \frac{1}{|C_{j}|} \sum_{u_{i} \in C_{j}}^{} c_{i}, j=1,2,3..,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;|C_{j}| &amp;lt;/math&amp;gt; - число элементов, принадлежащих кластеру &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 5&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Если алгоритм не завершил свою работу на шаге 3 то переходим к шагу 2.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром данного алгоритма является вычисление на каждой итерации алгоритма квадратов норм между кластерными центрами и векторами из входного набор согласно формуле &amp;lt;math&amp;gt;\|u_k-c_i\|^2&amp;lt;/math&amp;gt;. На каждой итерации алгоритма происходит &amp;lt;math&amp;gt;cK&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;&lt;br /&gt;
\|u_k-c_i\|^2&lt;br /&gt;
&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;J=\sum_{j = 1}^{c} \sum_{u_{i} \in C_{j}}^{} \|u_{i}-c_{j}\|^2,  j \in 1,2, ... c, i={1,2, ...K}&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; c^*_{j} = \frac{1}{|C_{j}|} \sum_{u_{i} \in C_{j}}^{} u_{i}, j=1,2,3..,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая &amp;lt;ref&amp;gt; Jyh-Shing Roger Jang, Chuen-Tsai Sun, Eiji Mizutani. Neuro-fuzzy and soft computing: a computational approach to learning and machine intelligence. Prentice-Hall, Inc. Simon &amp;amp; Schuster/A Viacom Company Upper Saddle River, NJ 07458. - 1997. - p. 424. [http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf]&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
1. Инициализация кластерных центров &amp;lt;math&amp;gt;c_i \, (i=1,2,\ldots,c)&amp;lt;/math&amp;gt;. Это можно сделать выбрав случайным образом &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; – векторов из входного набора. &lt;br /&gt;
&lt;br /&gt;
2. Вычисление рядовой матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ik} = \begin{cases}&lt;br /&gt;
1, &amp;amp; \|u_k-c_i\|^2 \leqslant \|u_k-c_j\|^2 \;\; \text{for all } i \neq j; \;\; (i,j=1,2,\ldots,c; \; k = 1,2,\ldots,K) \\&lt;br /&gt;
0, &amp;amp; \text{other}.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&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;&lt;br /&gt;
\sum\limits_{i=1}^c m_{ij} = 1, \;\; \sum\limits_{j=1}^K m_{ij} = K.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3. Расчёт объектной функции:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^c J_i = \sum\limits_{i=1}^c \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right)&lt;br /&gt;
.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На этом шаге происходит остановка и выход из цикла, если полученное значение ниже пороговой величины или полученное значение не сильно отличается от значений, полученных на предыдущих циклах.&lt;br /&gt;
&lt;br /&gt;
4. Пересчёт кластерных центров выполняется в соответствии со следующим уравнением:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;|C_i|&amp;lt;/math&amp;gt; подразумевается количество элементов в &amp;lt;math&amp;gt;i&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;n&amp;lt;/math&amp;gt; вычитаний, &amp;lt;math&amp;gt;n-1&amp;lt;/math&amp;gt; сложений  и &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; операций возведения в квадрат (умножений).&lt;br /&gt;
&lt;br /&gt;
Для каждой итерации алгоритма требуется:&lt;br /&gt;
* &amp;lt;math&amp;gt;ncK&amp;lt;/math&amp;gt; умножений,&lt;br /&gt;
* &amp;lt;math&amp;gt;ncK&amp;lt;/math&amp;gt; вычитаний,&lt;br /&gt;
* &amp;lt;math&amp;gt;K(cn+1)&amp;lt;/math&amp;gt; сложений,&lt;br /&gt;
* &amp;lt;math&amp;gt;K(c-1)&amp;lt;/math&amp;gt; сравнений.&lt;br /&gt;
&lt;br /&gt;
Умножения, сложения (вычитания), сравнения составляют &#039;&#039;основную часть алгоритма&#039;&#039;.&lt;br /&gt;
 &lt;br /&gt;
Итоговая сложность последовательной реализации алгоритма &amp;lt;math&amp;gt;O(ncK)&amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt; Pawan Kumar, Mr. Pankaj Verma, Rakesh Sharma. Comparative analysis of Fuzzy C-mean and Hard C-mean algorithm // International Journal of information Technology and Knowledge Management. - July-December 2010. - v. 2 [http://csjournals.com/IJITKM/PDF%203-1/39.pdf]&amp;lt;/ref&amp;gt;. Обычно &amp;lt;math&amp;gt;n&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;
=== Информационный граф ===&lt;br /&gt;
опишем граф как аналитически, так и в виде рисунка. &lt;br /&gt;
&lt;br /&gt;
Граф алгоритма состоит из пяти групп вершин.&lt;br /&gt;
 &lt;br /&gt;
&#039;&#039;&#039;Первая&#039;&#039;&#039; группа вершин &#039;&#039;&#039;&#039;&#039;&amp;lt;math&amp;gt;c_1,...,c_c&amp;lt;/math&amp;gt;&#039;&#039;&#039;&#039;&#039; - прямое вычисление расстояния до кластерных центров, то есть вычисление расстояний от заданного элемента &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; до каждого из кластерных центров.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вторая&#039;&#039;&#039; группа вершин &#039;&#039;&#039;&#039;&#039;min&#039;&#039;&#039;&#039;&#039; - ей соответствует вычисление минимального расстояния до кластерных центров,передача найденного минимального расстояния и соответствующего ему индекса кластера.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Третья&#039;&#039;&#039; группа вершин &#039;&#039;&#039;&#039;&#039;M&#039;&#039;&#039;&#039;&#039; - ей соответствует операция записи единички в столбец матрицы.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Четвертая&#039;&#039;&#039; группа вершин &#039;&#039;&#039;&#039;&#039;J&#039;&#039;&#039;&#039;&#039; - вычисление объектной функции, происходит проверка условия достижения необходимой точности, если достигли заданной точности то переход в &#039;&#039;&#039;&#039;&#039;Out&#039;&#039;&#039;&#039;&#039;, в противном случае &#039;&#039;&#039;&#039;&#039;Conversion&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Пятая&#039;&#039;&#039; группа вершин &#039;&#039;&#039;&#039;&#039;Conversion&#039;&#039;&#039;&#039;&#039; - пересчёт кластерных центров и переход на следующую итерацию.&lt;br /&gt;
&lt;br /&gt;
На рисунке изображена одна итерация алгоритма.&lt;br /&gt;
 &lt;br /&gt;
[[File:Picture.png|thumb|600px|center|Рисунок 1. &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; - входные данные, &#039;&#039;&#039;&#039;&#039;&amp;lt;math&amp;gt;c_1,...,c_c&amp;lt;/math&amp;gt;&#039;&#039;&#039;&#039;&#039; - вычисление расстояния до кластерных центров и значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; единое для каждой группы &#039;&#039;&#039;&#039;&#039;&amp;lt;math&amp;gt;c_1,...,c_c&amp;lt;/math&amp;gt;&#039;&#039;&#039;&#039;&#039;, &#039;&#039;&#039;&#039;&#039;min&#039;&#039;&#039;&#039;&#039; - нахождение минимального расстояния до кластерных центров, &#039;&#039;&#039;&#039;&#039;M&#039;&#039;&#039;&#039;&#039; - запись единички в столбец матрицы, &#039;&#039;&#039;&#039;&#039;J&#039;&#039;&#039;&#039;&#039; - расчёт объектной функции, &#039;&#039;&#039;&#039;&#039;Conversion&#039;&#039;&#039;&#039;&#039; — пересчёт кластерных центров, &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для одной итерации алгоритма в параллельном варианте требуется &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; раз последовательно выполнить для каждого &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; следующие ярусы:&lt;br /&gt;
* &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; операций нахождения расстояния от элемента &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; до каждого из кластерных центров.&lt;br /&gt;
* &amp;lt;math&amp;gt;C-1&amp;lt;/math&amp;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;u_i&amp;lt;/math&amp;gt;. Расчёт значения объектной функции &amp;lt;math&amp;gt;J&amp;lt;/math&amp;gt; сложно представить в параллельном варианте, поэтому вычисление объектной функции производится последовательно.Использование параллельной реализации алгоритма приведёт к понижению производительности при небольшой размерности системы и малом объеме выборки. При параллельном варианте необходима пересылка данных, что при малом объеме выборки и небольшой размерности займет больше времени, чем при последовательном варианте.&lt;br /&gt;
Как легко видеть из информационного графа, высота [[глоссарий#Ярусно-параллельная форма графа алгоритма|ЯПФ]] составляет &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;, ширина ЯПФ составляет &amp;lt;math&amp;gt;O(cK)&amp;lt;/math&amp;gt;, если число итераций меньше объема выборки.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; &lt;br /&gt;
# &amp;lt;math&amp;gt;\{u_k\}_{k=1}^{K}&amp;lt;/math&amp;gt; — исходный набор векторов, принадлежащие пространству &amp;lt;math&amp;gt;\mathbb{R}^n&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;nK&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
# &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; — матрица, принадлежащая пространству &amp;lt;math&amp;gt;\mathbb{R}^{c \times K}&amp;lt;/math&amp;gt;.&lt;br /&gt;
# &amp;lt;math&amp;gt;\{c^*_i\}_{i=1}^{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+n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Назначение:&#039;&#039;&#039; кластеризация больших наборов числовых данных. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Достоинства:&#039;&#039;&#039; легкость реализации,вычислительная простота.&lt;br /&gt;
 &lt;br /&gt;
&#039;&#039;&#039;Недостатки:&#039;&#039;&#039; задание количества кластеров,отсутствие гарантии в нахождении оптимального решения.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
Проведём исследование масштабируемости параллельной реализации алгоритма Hard C - Means (HCM). Исследование проводилось на суперкомпьютере &amp;quot;Ломоносов&amp;quot; [http://parallel.ru/cluster Суперкомпьютерного комплекса Московского университета] с пиковой производительностью 1,7 Пфлопс, число процессоров/ядер x86: 12 346 / 52 168. Программа написана на языке C с использованием [https://parallel.ru/cluster/lomonosov_howto MPI], не использовалось дополнительных опций. Использовалась следующая [https://github.com/cNikolaou/mpi-kmeans параллельная реализация алгоритма HCM].&lt;br /&gt;
Компилятор: gcc.&lt;br /&gt;
Версия MPI - intel openmpi/1.8.4-icc.&lt;br /&gt;
Модель используемого CPU - Intel Xeon X5570 2.93GHz.&lt;br /&gt;
&lt;br /&gt;
Набор и границы значений изменяемых [[Глоссарий#Параметры запуска|параметров запуска]] реализации алгоритма: &lt;br /&gt;
&lt;br /&gt;
*	число ядер &amp;lt;math&amp;gt;[16 : 256]&amp;lt;/math&amp;gt; с шагом по степеням двойки;&lt;br /&gt;
*	объём выборки &amp;lt;math&amp;gt;[10^3:10^7]&amp;lt;/math&amp;gt;  с шагом по степеням десятки;&lt;br /&gt;
&lt;br /&gt;
На рисунке приведена параллельная реализация алгоритма Hard C - Means (HCM). Изменение вычислительного времени алгоритма в зависимости от числа ядер и размера исходных данных. &lt;br /&gt;
&lt;br /&gt;
[[Файл:scheme1.png]]&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*  [https://github.com/artpar/Hard-Clustering-implementation Последовательная реализация на С++ ]&lt;br /&gt;
&lt;br /&gt;
*  [http://projects.jasmeet.me/2013/03/HardCMeans.html Последовательная реализация на MatLab ]&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Coctic</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:%D0%A8%D0%B8%D1%88%D0%BA%D0%BE%D0%B2_%D0%98%D0%BB%D1%8C%D1%8F_%D0%A1%D0%B5%D1%80%D0%B3%D0%B5%D0%B5%D0%B2%D0%B8%D1%87&amp;diff=21054</id>
		<title>Обсуждение участника:Шишков Илья Сергеевич</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:%D0%A8%D0%B8%D1%88%D0%BA%D0%BE%D0%B2_%D0%98%D0%BB%D1%8C%D1%8F_%D0%A1%D0%B5%D1%80%D0%B3%D0%B5%D0%B5%D0%B2%D0%B8%D1%87&amp;diff=21054"/>
		<updated>2016-12-16T13:04:00Z</updated>

		<summary type="html">&lt;p&gt;Coctic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Статья [[Алгоритм HCM (Hard C – Means)]] =&lt;br /&gt;
* Не указан вклад каждого автора [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:47, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:06, 1 ноября 2016 (MSK)&lt;br /&gt;
* п. 1.1 Стоит добавит ссылку на публикацию, в которой алгоритм был впервые описан (Jang, Sun and Mizutani) [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:47, 25 октября 2016 (MSK)&lt;br /&gt;
* Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:06, 1 ноября 2016 (MSK)&lt;br /&gt;
* п. 1.3 Сказано, что &amp;quot;На каждой итерации алгоритма происходит &amp;lt;math&amp;gt;CN&amp;lt;/math&amp;gt; таких вычислений&amp;quot;, однако определений C и N не приведено ни здесь, ни ранее. Ранее имеется определение для c (c малого), но это другой символ. [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:47, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:06, 1 ноября 2016 (MSK)&lt;br /&gt;
* Ссылки в списке литературы не содержат данных публикации, кроме названия и списка авторов. Веб-ссылки на какую-то версию публикации недостаточно. [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:52, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:06, 1 ноября 2016 (MSK)&lt;br /&gt;
** Замечания были приняты и исправлены огрехи. [[Участник:Темербекова_Гульгайша|Темербекова_Гульгайша]] ([[Обсуждение участника:Темербекова_Гульгайша|обсуждение]]) 23:40, 31 октября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
* Отсутствует п. 2.4. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 16:54, 16 ноября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 17:42, 13 декабря 2016 (MSK)&lt;br /&gt;
* Необходимо указать характеристики программно-аппаратной платформы (какой компилятор, с какими опциями использовался, какие версии библиотек, на каких узлах проводился запуск и т.д.). Указано, что запуск осуществлялся на Ломоносове, ссылка на MPI приведена на страницы, описывающие BlueGene/P, понять, какая реализация MPI использовалась, невозможно [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 17:42, 13 декабря 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 16:03, 16 декабря 2016 (MSK)&lt;br /&gt;
* На неподписанном рисунке в п. 2.4. в подписи к оси аппликат указано, что по ней отложено время в секундах, в абзаце перед рисунком указано, что приведен график производительности. Что из этого верно, неясно. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 17:42, 13 декабря 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 16:03, 16 декабря 2016 (MSK)&lt;/div&gt;</summary>
		<author><name>Coctic</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:Smirnov.maxim/BIRCH&amp;diff=20817</id>
		<title>Участник:Smirnov.maxim/BIRCH</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:Smirnov.maxim/BIRCH&amp;diff=20817"/>
		<updated>2016-12-13T14:44:21Z</updated>

		<summary type="html">&lt;p&gt;Coctic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|{{REVISIONUSER}}}}&lt;br /&gt;
Авторы: [[Участник:Светлана Морозова|Морозова Светлана]], [[Участник:Smirnov.maxim|Смирнов Максим]].&lt;br /&gt;
Вклад авторов:&lt;br /&gt;
&lt;br /&gt;
Смирнов Максим:&lt;br /&gt;
*п.1.5&lt;br /&gt;
*п.1.7&lt;br /&gt;
*п.1.8&lt;br /&gt;
*п.1.9&lt;br /&gt;
*п.2.7&lt;br /&gt;
&lt;br /&gt;
Морозова Светлана&lt;br /&gt;
*п.1.1&lt;br /&gt;
*п.1.2&lt;br /&gt;
*п.1.3&lt;br /&gt;
*п.1.4&lt;br /&gt;
*п.1.6&lt;br /&gt;
*п.1.10&lt;br /&gt;
*п.3&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Нахождение полезных для анализа закономерностей в больших объёмах данных с недавних пор вызывает значительный интерес. В связи с этим ввелось и стало активно развиваться такое понятие как &#039;&#039;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7 кластеризация]&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Ранние работы и алгоритмы, разработанные в этой области, не уделяли достаточного внимания анализу очень больших наборов данных или минимизации издержек на процессы ввода-вывода.&lt;br /&gt;
Решением этих проблем стал алгоритм, известный как BIRCH.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIRCH&#039;&#039;&#039;&amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации // Интеллектуальные технологии и системы. Сборник учебно-методических работ и статей аспирантов и студентов. – М.: НОК «CLAIM», 2006. – Выпуск 8. – С. 130-142.&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;T Zhang, R Ramakrishnan, M Livny. BIRCH: An Efficient Data Clustering Method for Very Large Databases - 1996. - С.103-114)&amp;lt;/ref&amp;gt; - алгоритм, применяемый в области [https://ru.wikipedia.org/wiki/Data_mining Data mining] и использующий принципы [https://ru.wikipedia.org/wiki/%D0%98%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F иерархической кластеризации].&lt;br /&gt;
&lt;br /&gt;
Если имеется очень большой набор данных, то в пространстве он распределен, как правило, неравномерно. Кластерный анализ определяет места наибольшего и наименьшего скоплений, чтобы таким образом понять всю картину целиком. Кроме того, полученные кластеры визуализируются гораздо нагляднее, чем начальные &amp;quot;сырые&amp;quot; данные.&lt;br /&gt;
Задачей алгоритмов кластеризации является не только простое разбиение данных на кластеры, но и работа в рамках ограниченного объёма доступной памяти (как правило, её объём гораздо меньше, чем размер исходного набора данных) и минимизация времени, требуемого на операции ввода-вывода.&lt;br /&gt;
&lt;br /&gt;
Для наилучшего решения этих проблем BIRCH распределяет входящие данные по кластерам динамически. Для эффективной кластеризации алгоритму требуется всего одно сканирование данных (т.е. с увеличением количества данных сложность увеличивается линейно). А при помощи одной (или более) дополнительных итераций можно и далее улучшать эффективность. BIRCH также является первым алгоритмом, предложенным для эффективного управления &amp;quot;шумами&amp;quot; (данными, которые не вписываются в общее представление модели).&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Теоретическая основа ===&lt;br /&gt;
&lt;br /&gt;
Пусть в кластере имеются &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}, i=1,2,...,N&amp;lt;/math&amp;gt;.&lt;br /&gt;
Тогда &#039;&#039;&#039;центроид&#039;&#039;&#039; &amp;lt;math&amp;gt;{\vec{{X_0}}}&amp;lt;/math&amp;gt;, &#039;&#039;&#039;радиус&#039;&#039;&#039; &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &#039;&#039;&#039;диаметр&#039;&#039;&#039; &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластера определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;{\vec{X_0}}=\frac{\sum_{i=1}^N\vec{X_i}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{\sum_{i=1}^N{(\vec{X_i} - \vec{X_0})}^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{\sum_{i=1}^N\sum_{j=1}^N{(\vec{X_i} - \vec{X_j})}^2}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; - это среднее расстояние от каждой точки до центроида. &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; - это среднее расстояние между парами в кластере. Данные величины являются альтернативными метриками плотности кластера относительно центроида.&lt;br /&gt;
&lt;br /&gt;
Для измерения близости друг к другу двух кластеров вводятся следующие метрики:&lt;br /&gt;
&lt;br /&gt;
пусть даны центроиды двух кластеров &amp;lt;math&amp;gt;\vec{X_{01}}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\vec{X_{02}}&amp;lt;/math&amp;gt;.&lt;br /&gt;
Евклидова метрика &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt; и метрика Манхэттена &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt; между двумя кластерами определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_0 = ((\vec{X_{01}}-\vec{X_{02}})^2)^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_1 = |\vec{X_{01}}-\vec{X_{02}}| = \sum_{i=1}^d |{\vec{X_{01}}}^{(i)}-{\vec{X_{02}}}^{(i)}| &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть имеются два кластера, содержащих соответственно  &amp;lt;math&amp;gt;N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;N_2&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i= 1,2, ...,N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\{\vec{X_j}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j= N_1+1,N_1+2, ...,N_1+N_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Среднее расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &#039;&#039;&#039;среднее внутрикластерное расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &#039;&#039;&#039;дисперсия&#039;&#039;&#039; &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; для двух кластеров определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{\sum_{i=1}^{N_1}\sum_{j=N_1+1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{N_1N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{\sum_{i=1}^{N_1+N_2}\sum_{j=1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_4 = \sum_{k=1}^{N_1+N_2}(\vec{X_k} - \frac{\sum_{i=1}^{N_1+N_2}\vec{X_i}}{N_1+N_2})^2 - \sum_{i=1}^{N_1}(\vec{X_i} - \frac{\sum_{i=1}^{N_1}\vec{X_i}}{N_1})^2 - \sum_{j=N_1+1}^{N_1+N_2}(\vec{X_j} - \frac{\sum_{i=N_1+1}^{N_1+N_2}\vec{X_i}}{N_2})^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Таким образом, величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; относятся к отдельным кластерам, а &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; - к объединению двух кластеров.&lt;br /&gt;
&lt;br /&gt;
=== Кластерный элемент и кластерное дерево ===&lt;br /&gt;
&lt;br /&gt;
В основе концепции алгоритма BIRCH лежат понятия &#039;&#039;&#039;кластерного элемента&#039;&#039;&#039; и &#039;&#039;&#039;кластерного дерева (CF Tree)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====Кластерный элемент ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; Пусть в кластере содержатся  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности  &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;:&amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;i=1,2,...,N&amp;lt;/math&amp;gt;. &lt;br /&gt;
&#039;&#039;&#039;Кластерный элемент (CF)&#039;&#039;&#039; - тройка чисел, характеризующая информацию о кластере: &lt;br /&gt;
&amp;lt;math&amp;gt;CF = (N, \vec{LS}, SS)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - количество элементов входных данных, содержащихся в кластере, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; - линейная сумма входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}\vec{X_i}&amp;lt;/math&amp;gt;), &amp;lt;math&amp;gt;SS&amp;lt;/math&amp;gt; - сумма квадратов входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}{\vec{X_i}}^2&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Теорема&#039;&#039;&#039; Пусть &amp;lt;math&amp;gt;CF_1 = (N_1, \vec{LS_1}, SS_1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;CF_2 = (N_1, \vec{LS_2}, SS_2)&amp;lt;/math&amp;gt; - CF векторы двух непересекающихся кластеров. Тогда при их объединении образуется кластер со следующим CF вектором: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF = CF_1 + CF_2 = (N_1+N_2, \vec{LS_1}+\vec{LS_2}, SS_1+SS_2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Из указанных выше определения и теоремы вытекает тот факт, что при объединении кластеров их CF вектор может вычисляться инкрементно и точно. &lt;br /&gt;
Легко показать, что вычислить величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;, как и обычные метрики, также не составит труда.&lt;br /&gt;
&lt;br /&gt;
Таким образом, в данном случае информацией о кластере является не весь набор точек, а вектор CF. Хранение одного только вектора может показаться неэффективным, но этого вполне достаточно для оперирования всеми необходимыми метриками, на основе которых принимаются решения в алгоритме BIRCH.&lt;br /&gt;
&lt;br /&gt;
==== Кластерное дерево ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; &#039;&#039;&#039;Кластерное дерево (CF Tree)&#039;&#039;&#039; - это взвешенно сбалансированное дерево с двумя параметрами: &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - коэффициент разветвления, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - пороговая величина.&lt;br /&gt;
&lt;br /&gt;
Каждый нелистьевой узел дерева имеет не более чем &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; вхождений узлов следующей формы: &amp;lt;math&amp;gt;[CF_i,child_i]&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i=1,2,...,B&amp;lt;/math&amp;gt;, &#039;&#039;child&#039;&#039; - указатель на i-й дочерний узел, &amp;lt;math&amp;gt;CF_i&amp;lt;/math&amp;gt; - CF вектор соответствующего подкластера.&lt;br /&gt;
&lt;br /&gt;
Каждый листьевой узел имеет ссылку на два соседних узла (&#039;&#039;prev&#039;&#039; и &#039;&#039;next&#039;&#039;) для того, чтобы связать все узлы для эффективного сканирования.&lt;br /&gt;
Все листьевые узлы должны удовлетворять пороговому ограничению &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, т.е. диаметр (радиус) не должен превосходить &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;.&lt;br /&gt;
В процессе вставки новых данных CF дерево строится динамически. Оно использует вставку данных для кластеризации точно также как &amp;lt;math&amp;gt;B+&amp;lt;/math&amp;gt; [https://ru.wikipedia.org/wiki/B%2B-%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE дерево] использует её для поиска.&lt;br /&gt;
CF дерево очень компактно, поскольку каждый листьевой узел - это не просто точка, а подкластер (который объединяет множество точек с учётом ограничения &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Операция вставки в &#039;&#039;&#039;CF&#039;&#039;&#039; дерево ====&lt;br /&gt;
&lt;br /&gt;
Опишем алгоритм вставки элемнта &amp;lt;math&amp;gt;Ent&amp;lt;/math&amp;gt; в CF дерево:&lt;br /&gt;
&lt;br /&gt;
1) &#039;&#039;Определение подходящего листа&#039;&#039;: Начиная с корня, алгоритм рекурсивно спускается по CF дереву, выбирая &#039;&#039;&#039;ближайший&#039;&#039;&#039; дочерний узел в соответствии с выбранной метрикой &amp;lt;math&amp;gt;D0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D4&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &#039;&#039;Преобразование листа&#039;&#039;: Когда алгоритм доходит до листа, он находит ближайшую листьевой элемент, скажем, &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;, а затем проверяет, можно ли добавить &#039;&#039;Ent&#039;&#039; к &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt; без нарушения порогового условия. Если да, то с учётом этого изменяется CF вектор для &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;; если нет, то &#039;&#039;Ent&#039;&#039; становится новым элементом листа. Если в листе для этого достаточно места, то шаг окончен, иначе он должен &amp;quot;расщепиться&amp;quot;. Расщепление узла производится при помощи выбора за основу наиболее удалённой друг от друга пары элементов и перераспределение оставшихся элементов в соответствии с выбранным критерием близости.&lt;br /&gt;
&lt;br /&gt;
3) &#039;&#039;Преобразование пути к листу&#039;&#039;: После вставки &#039;&#039;Ent&#039;&#039; в лист мы должны обновить информацию о CF для каждого нелистьевого элемента на пути к листу. При отсутствии расщепления это означает простое сложение CF векторов для отражения факта добавления &#039;&#039;Ent&#039;&#039;. Расщепление листа же требует вставки нового нелистьевого элемента в родительский узел для задания только что созданного листа. Если у родителя есть место для этого элемента, то необходимо просто преобразовать CF векторы на всех более высоких уровнях. В общем случае, однако, нам также придётся расщепить родительский узел, и так далее до корня. Если расщеплён корень, то высота дерева увеличивается на единицу.&lt;br /&gt;
&lt;br /&gt;
4) &#039;&#039;Улучшение слияния&#039;&#039;: Расщепление вызвано ограничением на размер узла, который не зависит от кластеризационных свойств данных. Если во входящем потоке присутствуют &amp;quot;искажённые&amp;quot; (из областей с низкой плотностью) данные, это может повлиять на качество кластеризации, а также уменьшить эффективность использования памяти. Дополнительный шаг алгоритма помогает решить эти проблемы: предположим, что произошло расщепление листа, и распространение этого процесса остановилось на некотором нелистьевом узле &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt;, то есть &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; может вместить дополнительный элемент, полученный после расщепления. Теперь мы сканируем узел &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; для нахождения двух наиболее близких элементов. Если это не пара, отвечающая расщеплению, мы пытаемся объединить их и поставить в соответствие два дочерних узла. Если количество элементов в дочерних узлах  больше B, мы снова расщепляем результат объединения.&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;R&amp;lt;/math&amp;gt; или диаметра &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластерного элемента. Выполняется при попытке вставить новый элемент в один из подкластеров листьевого узла дерева.&lt;br /&gt;
&lt;br /&gt;
* расстояния между двумя элементами. Выполняется при поиске ближайшего по отношению к новому элементу подкластера в узле дерева по одной из рассмотренных в разд. 1.2.1 метрик &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Зная характеристики кластерных элементов &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;, в результате алгебраических преобразований можно получить следующие упрощенные формулы вычисления необходимых значений:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\vec{X_0} = \frac{\vec{LS}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{SS - 2\vec{X_0}\vec{LS} + N(\vec{X_0})^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{2(N \cdot SS - (\vec{LS})^2)}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{N_1 \cdot SS_2 + N_2 \cdot SS_1 - 2\vec{LS_1}\vec{LS_2}}{N_1 \cdot N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{2((N_1+N_2)(SS_1+SS_2)-(\vec{LS_1}+\vec{LS_2})^2)}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Реализация алгоритма BIRCH состояит из следующих четырёх фаз:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 1&#039;&#039;&#039;. Главной задачей фазы 1 является сканирование всех данных и построение в памяти исходного CF дерева, используя заданное количество памяти. Это дерево стремится отразить информацию о кластеризации данных настолько хорошо, насколько это позволяют ограничения по памяти. При этом плотно распределённые данные группируются в подкластеры, а более разрозненные данные удаляются. После завершения фазы 1 вспомогательные вычисления в дальнейших фазах будут:&lt;br /&gt;
&lt;br /&gt;
1) быстрее, потому что (а) больше не нужны операции ввода-вывода, (b) проблема кластеризации начальных данных упрощается до проблемы кластеризации подкластеров в листьях;&lt;br /&gt;
&lt;br /&gt;
2) точнее, потому что (а) большинство данных с низкой плотностью удалены, (b) оставшиеся данные распределены оптимально (в соответствии с доступным количеством памяти);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 2&#039;&#039;&#039;. Данная фаза является опциональной. Известно, что существующие методы глобальной кластеризации, используемые в рамках фазы 3, имеют различные диапазоны входных значений, при которых их реализация наиболее эффективна. Поэтому потенциально существует пробел между размером фазы 1 и входными значениями фазы 3. И фаза 2 как раз является недостающим связующим звеном: так же как и фаза 1, она сканирует листьевые элементы начального CF дерева для того, чтобы построить меньшее дерево, удаляя ещё больше элементов с низкой плотностью и группируя переполненные подкластеры в большие кластеры.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 3&#039;&#039;&#039;. В данной фазе для листьевых элементов применяется (любой подходящий) алгоритм глобальной кластеризации. Существующие алгоритмы кластеризации наборов точек могут также работать с наборами подкластеров, каждый из которых представлен своим CF вектором. Зная CF вектор, можно вычислить центроид и в дальнейшем заменить всю информацию о кластере этим значением (этого достаточно для вычисления большинства необходимых метрик). После фазы 3 мы получаем набор кластеров, который отражает основные характеристики распределяемых данных.&lt;br /&gt;
Однако, всё ещё могут оставаться некоторые неточности, для устранения которых существует фаза 4.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 4&#039;&#039;&#039;. Данная фаза является опциональной и влечёт за собой затраты на дополнительное сканирование данных для корректировки неточностей и дальнейшего улучшения кластеризации. Фаза 4 использует центроиды кластеров, полученные в фазе 3 для как основы и перераспределяет точки входных данных в ближайшие для них основы для получения нового списка кластеров. Фаза 4, если это необходимо пользователю, может быть расширена дополнительными проходами для уверенности в том, что результат приближается к оптимальному.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Последовательную реализацию основных операций алгоритма BIRCH можно продемонстрировать на примере следующего фрагмента кода на языке C++:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot;&amp;gt;&lt;br /&gt;
void CF_Node::insert(const CF_Cluster &amp;amp;entry)&lt;br /&gt;
{&lt;br /&gt;
    //Находим ближайший к новому элементу подкластер в узле&lt;br /&gt;
    СF_Vector_it closest = entry.findClosest(subclusters);&lt;br /&gt;
    //Если узел пустой, добавляем в него новый подкластер&lt;br /&gt;
    if (closest == subclusters.end()) {&lt;br /&gt;
        subclusters.push_back(entry);&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    closest-&amp;gt;add(entry);&lt;br /&gt;
    //Если узел является листьевым, и ближайший подкластер не может вместить&lt;br /&gt;
    //новый элемент, добавляем в узел новый подкластер&lt;br /&gt;
    if (leaf) {&lt;br /&gt;
        if (closest-&amp;gt;D &amp;gt; threshold) {&lt;br /&gt;
            closest-&amp;gt;remove(entry);&lt;br /&gt;
            subclusters.push_back(entry);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else {&lt;br /&gt;
        CF_Node *node = closest-&amp;gt;child;&lt;br /&gt;
        node-&amp;gt;insert(entry);&lt;br /&gt;
        //Если при добавлении нового элемента в дочерний узел тот переполнился,&lt;br /&gt;
        //расщепляем его        &lt;br /&gt;
        if (node-&amp;gt;getSubclusters().size() &amp;gt; bFactor) {&lt;br /&gt;
            CF_Vector newClusters = node-&amp;gt;splitNode();&lt;br /&gt;
            delete node;&lt;br /&gt;
            subclusters.erase(closest);&lt;br /&gt;
            subclusters.insert(subclusters.end(), newClusters.begin(), newClusters.end());&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    //Если узел является корневым и он переполнен, расщепляем его&lt;br /&gt;
    if (root &amp;amp;&amp;amp; subclusters.size() &amp;gt; bFactor) {&lt;br /&gt;
        subclusters = splitNode();&lt;br /&gt;
        leaf = false;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
CF_Vector CF_Node::splitNode()&lt;br /&gt;
{&lt;br /&gt;
    if (subclusters.size() &amp;lt; 2)&lt;br /&gt;
        return (root) ? subclusters : CF_Vector{CF_Cluster(this)};&lt;br /&gt;
    //Находим пару наиболее удаленных друг от друга подкластеров&lt;br /&gt;
    CF_Vector_it pole1, pole2;&lt;br /&gt;
    data_t longestDist = 0.0;&lt;br /&gt;
    for (auto lhs = subclusters.begin(); lhs != subclusters.end() - 1; ++lhs) {&lt;br /&gt;
        for (auto rhs = lhs + 1; rhs != subclusters.end(); ++rhs) {&lt;br /&gt;
            auto distance = getDistance(*lhs, *rhs);&lt;br /&gt;
            if (distance &amp;gt; longestDist) {&lt;br /&gt;
                longestDist = distance;&lt;br /&gt;
                pole1 = lhs;&lt;br /&gt;
                pole2 = rhs;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    //Разделяем множество всех подкластеров узла на две части&lt;br /&gt;
    CF_Vector subclusters1, subclusters2;&lt;br /&gt;
    for (auto it = subclusters.begin(); it != subclusters.end(); ++it) {&lt;br /&gt;
        if (getDistance(*it, *pole1) &amp;lt; getDistance(*it, *pole2))&lt;br /&gt;
            subclusters1.push_back(*it);&lt;br /&gt;
        else&lt;br /&gt;
            subclusters2.push_back(*it);&lt;br /&gt;
    }&lt;br /&gt;
    //Создаем два новых узла&lt;br /&gt;
    CF_Node *node1 = new CF_Node(threshold, bFactor, count, leaf, subclusters1),&lt;br /&gt;
            *node2 = new CF_Node(threshold, bFactor, count, leaf, subclusters2);&lt;br /&gt;
    //Связываем листья&lt;br /&gt;
    if (leaf) {&lt;br /&gt;
        if (prevLeaf) {&lt;br /&gt;
            node1-&amp;gt;setPrevLeaf(prevLeaf);&lt;br /&gt;
            prevLeaf-&amp;gt;setNextLeaf(node1);&lt;br /&gt;
        }&lt;br /&gt;
        if (nextLeaf) {&lt;br /&gt;
            node2-&amp;gt;setNextLeaf(nextLeaf);&lt;br /&gt;
            nextLeaf-&amp;gt;setPrevLeaf(node2);&lt;br /&gt;
        }&lt;br /&gt;
        node1-&amp;gt;setNextLeaf(node2);&lt;br /&gt;
        node2-&amp;gt;setPrevLeaf(node1);&lt;br /&gt;
    }&lt;br /&gt;
    CF_Cluster cluster1(node1), cluster2(node2);&lt;br /&gt;
    return CF_Vector{cluster1, cluster2};&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Для начала проанализируем вычислительную сложность фазы 1.&lt;br /&gt;
Максимальный размер дерева &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt; - ограничение по памяти на размер узла, а &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - общий объем памяти. Для того чтобы вставить элемент, мы должны пройти путь от корня до листа (это около &amp;lt;math&amp;gt;1+log_B\frac{M}{P}&amp;lt;/math&amp;gt; узлов). В каждом узле в поисках &amp;quot;ближайшего&amp;quot; нам необходимо просмотреть B элементов; сложность для каждого элемента пропорциональна размерности &#039;&#039;d&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Поэтому сложность вставки всех входных точек &amp;lt;math&amp;gt;O(d \cdot N \cdot B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В случае, когда необходимо перестроить дерево, предположим, что ES - это размер CF элемента. Существует максимум &amp;lt;math&amp;gt;\frac{M}{ES}&amp;lt;/math&amp;gt; листьевых элементов для вставки, поэтому сложность повторной вставки листьевых элементов &amp;lt;math&amp;gt;O(d \cdot \frac{M}{ES} \cdot B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Количество итераций перестройки дерева зависит от пороговой величины. На самом деле, это около &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; (двоичное основание появилось из-за того, что мы не можем провести оценку более чем в 2 раза отличающуюся от текущего размера). &amp;lt;math&amp;gt;N_0&amp;lt;/math&amp;gt; - это число входных точек, загруженных в память с пороговым ограничением &amp;lt;math&amp;gt;T_0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Соответственно, итоговая сложность фазы 1 &amp;lt;math&amp;gt;O(d \cdot N \cdot B(1+log_B\frac{M}{P})+log_2\frac{N}{N_0} \cdot d \cdot \frac{M}{ES} \cdot B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Анализ фазы 2 проводится аналогично.&lt;br /&gt;
&lt;br /&gt;
Что касается операций ввода-вывода, то в фазе 1 данные сканируются один раз, а в фазе 2 не сканируются вовсе.&lt;br /&gt;
Некоторое количество вычислений связано с удалением точек из областей с низкой плотностью.&lt;br /&gt;
Если количество доступной для этой операции памяти не больше &#039;&#039;M&#039;&#039; и проведено порядка &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; перестроек дерева, то сложность ввода-вывода для фазы 1 существенно не отличается от сложности чтения из файла. Основываясь рассуждениях выше, сложность фаз 1 и 2 будет линейно увеличиваться с ростом N.&lt;br /&gt;
&lt;br /&gt;
В фазе 3 нет операций ввода-вывода. Её сложность ограничена константой, которая зависит от максимального размера входных данных, и варианта выбранного алгоритма для кластеризации. &lt;br /&gt;
&lt;br /&gt;
Фаза 4 снова сканирует данные и записывает каждую точку в подходящий кластер; время работы пропорционально &amp;lt;math&amp;gt;N \cdot K&amp;lt;/math&amp;gt;.   &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&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;D_2=\frac{N_1\cdot SS_2+N_2\cdot SS_1-2 \cdot \vec{LS_1}\cdot \vec{LS_2}}{N_1\cdot N_2}&amp;lt;/math&amp;gt;, где&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF_1=[N_1,\vec{LS_1},SS_1]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF_2=[N_2,\vec{LS_2},SS_2]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:ZgYL51QJsQk.jpg|600px|thumb|center]]&lt;br /&gt;
&lt;br /&gt;
=== Поиск ближайшего подкластера ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;E&amp;lt;/math&amp;gt; - новый элемент&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF_i, i = 1,...,B&amp;lt;/math&amp;gt; - подкластеры узла&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - операция min&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\rho&amp;lt;/math&amp;gt; - нахождение расстояния&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:PFA16KHUQ3I.jpg|600px|thumb|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Скалярное произведение ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;s = \vec{x}\cdot\vec{y}=\sum_{i=1}^d x_i\cdot y_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Xb7FYXVMPpQ.jpg|600px|thumb|center]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&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;\vec{LS},\vec{X0}, R, D, D_0-D_4&amp;lt;/math&amp;gt;, в процессе чего выполняются операции сложения и скалярного произведения векторов.&lt;br /&gt;
&lt;br /&gt;
Таким образом, параллельная сложность фазы 1 алгоритма будет равна &amp;lt;math&amp;gt;O((N + log_2\frac{N}{N_0} \cdot \frac{M}{ES})(log_2 B + log_2 d)(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Другим способом параллелизации алгоритма может служить создание и заполнение сразу множества кластерных деревьев, между которыми будут распределены входные данные. Множество всех подкластеров листьевых узлов полученных таким образом деревьев может быть подвергнуто глобальной кластеризации с помощью какого-либо из известных параллельных алгоритмов, например, k-средних&amp;lt;ref&amp;gt;[A Garg, N Gupta PBIRCH: A Scalable Parallel Clustering algorithm for Incremental Data //10th International Database Engineering and Applications Symposium (IDEAS&#039;06), 2006&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; набор из &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек &amp;lt;math&amp;gt;\{X_i\}, i=1,...,N&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем входных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;N \cdot d&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; кластерное дерево с не более чем &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt; узлами.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительная мощность алгоритма имеет порядок &amp;lt;math&amp;gt;O(\frac{d \cdot B \cdot (1+log_B\frac{M}{P}) \cdot (N +log_2\frac{N}{N_0} \cdot \frac{M}{ES})}{N \cdot d + M})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм BIRCH не является детерминированным, так как процесс его выполнения во многом зависит от входных данных.&lt;br /&gt;
&lt;br /&gt;
К достоинствам алгоритма можно отнести следующие его свойства:&lt;br /&gt;
&lt;br /&gt;
1. BIRCH является локальным алгоритмом, то есть каждое решение о каждом элементе кластера принимается без повторного сканирования данных или уже существующих кластеров. Используются только метрики, отражающие близость элементов друг к другу.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH использует факт неравномерного распределения данных в пространстве и поэтому не все данные рассматриваются как одинаково важные для построения кластера. Области с большой плотностью обрабатываются как единый кластер. Данные в более разреженных областях могут удаляться (опционально).&lt;br /&gt;
&lt;br /&gt;
3. BIRCH использует всю доступную память для получения наилучших из возможных подкластеров, в то же время минимизируя затраты на операции ввода/вывода. Оптимизация процесса кластеризации достигается за счет использования взвешенно-сбалансированного дерева. При этом время исполнения линейно.&lt;br /&gt;
&lt;br /&gt;
4. BIRCH не требует всего набора данных заранее (при этом просматривает его всего один раз).&lt;br /&gt;
&lt;br /&gt;
В свою очередь, недостатки алгоритма можно сформулировать следующим образом:&lt;br /&gt;
&lt;br /&gt;
1. Алгоритм позволяет работать только с числовыми данными.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH хорошо выделяет только кластеры сферической формы.&lt;br /&gt;
&lt;br /&gt;
3. Существует необходимость в задании пороговых значений.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
Проведём исследование масштабируемости параллельной реализации алгоритма BIRCH. Исследование проводилось на суперкомпьютере &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;
[[file:Масштабируемость параллельной реализации алгоритма BIRCH. Производительность.png|thumb|center|700px|Рисунок 1. График времени работы параллельной реализации алгоритма BIRCH. ]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[file:Масштабируемость параллельной реализации алгоритма BIRCH. Эффективность.png|thumb|center|700px|Рисунок 2. График эффективности распараллеливания алгоритма BIRCH относительно последовательной реализации. ]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Набор изменяемых параметров запуска реализации алгоритма и границы значений параметров алгоритма: &lt;br /&gt;
*	число процессоров [8 : 80] с шагом 8&lt;br /&gt;
*	число точек [100 000 : 1 000 000] с шагом 100 000&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В результате проведённых экспериментов был получен следующий диапазон эффективности реализации алгоритма:&lt;br /&gt;
*	минимальная эффективность реализации 9,13% (80 процессоров, 100 000 точек)&lt;br /&gt;
*	максимальная эффективность реализации 235,42% (8 процессоров, 800 000 точек)&lt;br /&gt;
&lt;br /&gt;
Полученные результаты могут быть объяснены недерминированностью алгоритма BIRCH и существенной зависимостью времени его работы от входных данных.&lt;br /&gt;
&lt;br /&gt;
Оценка масштабируемости параллельной реализации:&lt;br /&gt;
*	По числу процессов:  при увеличении числа процессов эффективность распараллеливания снижается. При количестве процессов &amp;lt;math&amp;gt;n&amp;gt;30&amp;lt;/math&amp;gt; темп снижения становится несущественным.&lt;br /&gt;
* По размеру задачи: при увеличении размера входных данных эффективность растет неравномерно, что свидетельствует о сложной зависимости от входных данных.&lt;br /&gt;
&lt;br /&gt;
Для исследования возможностей паралеллизма алгоритма BIRCH была написана [https://github.com/duran-duran/birch реализация на языке C++] с использованием технологии MPI. В данной реализации входные данные равномерно распределяются между всеми процессами, в каждом из которых выполняется построение собственного кластерного дерева. Листьевые элементы полученных деревьев затем подвергаются глобальной кластеризации с помощью распределенного алгоритма k-средних. В качестве входных данных использовались точки размерности &amp;lt;math&amp;gt;d=5&amp;lt;/math&amp;gt;, координаты которых были равномерно распределены в диапазоне &amp;lt;math&amp;gt;[-10000;10000]&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable mw-collapsible mw-collapsed&amp;quot;&lt;br /&gt;
! Технические детали реализации&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
Компилятор: intel/15.0.090&lt;br /&gt;
&lt;br /&gt;
Версия реализации MPI: openmpi/1.10.2-icc&lt;br /&gt;
&lt;br /&gt;
Планировщик задач: slurm/2.5.6&lt;br /&gt;
&lt;br /&gt;
Очереди: test, regular4&lt;br /&gt;
&lt;br /&gt;
Команда компиляции: mpicxx -std=c++11 -Wall &amp;lt;source_files&amp;gt; -o &amp;lt;executable&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Команда запуска: sbatch -n &amp;lt;num_of_processes&amp;gt; -p &amp;lt;queue&amp;gt; -o &amp;lt;log_file&amp;gt; ompi &amp;lt;executable&amp;gt; &amp;lt;args&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;
* [http://scikit-learn.org/stable/modules/generated/sklearn.cluster.Birch.html scikit-learn]&lt;br /&gt;
* [http://cucis.ece.northwestern.edu/projects/DMS/MineBench.html NU-MineBench]&lt;br /&gt;
Пользовательские реализации:&lt;br /&gt;
* [https://code.google.com/archive/p/jbirch/ JBIRCH]&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Coctic</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:Smirnov.maxim/BIRCH&amp;diff=20816</id>
		<title>Участник:Smirnov.maxim/BIRCH</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:Smirnov.maxim/BIRCH&amp;diff=20816"/>
		<updated>2016-12-13T14:44:05Z</updated>

		<summary type="html">&lt;p&gt;Coctic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|{REVISIONUSER}}}}&lt;br /&gt;
Авторы: [[Участник:Светлана Морозова|Морозова Светлана]], [[Участник:Smirnov.maxim|Смирнов Максим]].&lt;br /&gt;
Вклад авторов:&lt;br /&gt;
&lt;br /&gt;
Смирнов Максим:&lt;br /&gt;
*п.1.5&lt;br /&gt;
*п.1.7&lt;br /&gt;
*п.1.8&lt;br /&gt;
*п.1.9&lt;br /&gt;
*п.2.7&lt;br /&gt;
&lt;br /&gt;
Морозова Светлана&lt;br /&gt;
*п.1.1&lt;br /&gt;
*п.1.2&lt;br /&gt;
*п.1.3&lt;br /&gt;
*п.1.4&lt;br /&gt;
*п.1.6&lt;br /&gt;
*п.1.10&lt;br /&gt;
*п.3&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Нахождение полезных для анализа закономерностей в больших объёмах данных с недавних пор вызывает значительный интерес. В связи с этим ввелось и стало активно развиваться такое понятие как &#039;&#039;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7 кластеризация]&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Ранние работы и алгоритмы, разработанные в этой области, не уделяли достаточного внимания анализу очень больших наборов данных или минимизации издержек на процессы ввода-вывода.&lt;br /&gt;
Решением этих проблем стал алгоритм, известный как BIRCH.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIRCH&#039;&#039;&#039;&amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации // Интеллектуальные технологии и системы. Сборник учебно-методических работ и статей аспирантов и студентов. – М.: НОК «CLAIM», 2006. – Выпуск 8. – С. 130-142.&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;T Zhang, R Ramakrishnan, M Livny. BIRCH: An Efficient Data Clustering Method for Very Large Databases - 1996. - С.103-114)&amp;lt;/ref&amp;gt; - алгоритм, применяемый в области [https://ru.wikipedia.org/wiki/Data_mining Data mining] и использующий принципы [https://ru.wikipedia.org/wiki/%D0%98%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F иерархической кластеризации].&lt;br /&gt;
&lt;br /&gt;
Если имеется очень большой набор данных, то в пространстве он распределен, как правило, неравномерно. Кластерный анализ определяет места наибольшего и наименьшего скоплений, чтобы таким образом понять всю картину целиком. Кроме того, полученные кластеры визуализируются гораздо нагляднее, чем начальные &amp;quot;сырые&amp;quot; данные.&lt;br /&gt;
Задачей алгоритмов кластеризации является не только простое разбиение данных на кластеры, но и работа в рамках ограниченного объёма доступной памяти (как правило, её объём гораздо меньше, чем размер исходного набора данных) и минимизация времени, требуемого на операции ввода-вывода.&lt;br /&gt;
&lt;br /&gt;
Для наилучшего решения этих проблем BIRCH распределяет входящие данные по кластерам динамически. Для эффективной кластеризации алгоритму требуется всего одно сканирование данных (т.е. с увеличением количества данных сложность увеличивается линейно). А при помощи одной (или более) дополнительных итераций можно и далее улучшать эффективность. BIRCH также является первым алгоритмом, предложенным для эффективного управления &amp;quot;шумами&amp;quot; (данными, которые не вписываются в общее представление модели).&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Теоретическая основа ===&lt;br /&gt;
&lt;br /&gt;
Пусть в кластере имеются &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}, i=1,2,...,N&amp;lt;/math&amp;gt;.&lt;br /&gt;
Тогда &#039;&#039;&#039;центроид&#039;&#039;&#039; &amp;lt;math&amp;gt;{\vec{{X_0}}}&amp;lt;/math&amp;gt;, &#039;&#039;&#039;радиус&#039;&#039;&#039; &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &#039;&#039;&#039;диаметр&#039;&#039;&#039; &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластера определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;{\vec{X_0}}=\frac{\sum_{i=1}^N\vec{X_i}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{\sum_{i=1}^N{(\vec{X_i} - \vec{X_0})}^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{\sum_{i=1}^N\sum_{j=1}^N{(\vec{X_i} - \vec{X_j})}^2}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; - это среднее расстояние от каждой точки до центроида. &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; - это среднее расстояние между парами в кластере. Данные величины являются альтернативными метриками плотности кластера относительно центроида.&lt;br /&gt;
&lt;br /&gt;
Для измерения близости друг к другу двух кластеров вводятся следующие метрики:&lt;br /&gt;
&lt;br /&gt;
пусть даны центроиды двух кластеров &amp;lt;math&amp;gt;\vec{X_{01}}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\vec{X_{02}}&amp;lt;/math&amp;gt;.&lt;br /&gt;
Евклидова метрика &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt; и метрика Манхэттена &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt; между двумя кластерами определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_0 = ((\vec{X_{01}}-\vec{X_{02}})^2)^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_1 = |\vec{X_{01}}-\vec{X_{02}}| = \sum_{i=1}^d |{\vec{X_{01}}}^{(i)}-{\vec{X_{02}}}^{(i)}| &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть имеются два кластера, содержащих соответственно  &amp;lt;math&amp;gt;N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;N_2&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i= 1,2, ...,N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\{\vec{X_j}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j= N_1+1,N_1+2, ...,N_1+N_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Среднее расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &#039;&#039;&#039;среднее внутрикластерное расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &#039;&#039;&#039;дисперсия&#039;&#039;&#039; &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; для двух кластеров определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{\sum_{i=1}^{N_1}\sum_{j=N_1+1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{N_1N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{\sum_{i=1}^{N_1+N_2}\sum_{j=1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_4 = \sum_{k=1}^{N_1+N_2}(\vec{X_k} - \frac{\sum_{i=1}^{N_1+N_2}\vec{X_i}}{N_1+N_2})^2 - \sum_{i=1}^{N_1}(\vec{X_i} - \frac{\sum_{i=1}^{N_1}\vec{X_i}}{N_1})^2 - \sum_{j=N_1+1}^{N_1+N_2}(\vec{X_j} - \frac{\sum_{i=N_1+1}^{N_1+N_2}\vec{X_i}}{N_2})^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Таким образом, величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; относятся к отдельным кластерам, а &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; - к объединению двух кластеров.&lt;br /&gt;
&lt;br /&gt;
=== Кластерный элемент и кластерное дерево ===&lt;br /&gt;
&lt;br /&gt;
В основе концепции алгоритма BIRCH лежат понятия &#039;&#039;&#039;кластерного элемента&#039;&#039;&#039; и &#039;&#039;&#039;кластерного дерева (CF Tree)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====Кластерный элемент ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; Пусть в кластере содержатся  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности  &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;:&amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;i=1,2,...,N&amp;lt;/math&amp;gt;. &lt;br /&gt;
&#039;&#039;&#039;Кластерный элемент (CF)&#039;&#039;&#039; - тройка чисел, характеризующая информацию о кластере: &lt;br /&gt;
&amp;lt;math&amp;gt;CF = (N, \vec{LS}, SS)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - количество элементов входных данных, содержащихся в кластере, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; - линейная сумма входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}\vec{X_i}&amp;lt;/math&amp;gt;), &amp;lt;math&amp;gt;SS&amp;lt;/math&amp;gt; - сумма квадратов входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}{\vec{X_i}}^2&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Теорема&#039;&#039;&#039; Пусть &amp;lt;math&amp;gt;CF_1 = (N_1, \vec{LS_1}, SS_1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;CF_2 = (N_1, \vec{LS_2}, SS_2)&amp;lt;/math&amp;gt; - CF векторы двух непересекающихся кластеров. Тогда при их объединении образуется кластер со следующим CF вектором: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF = CF_1 + CF_2 = (N_1+N_2, \vec{LS_1}+\vec{LS_2}, SS_1+SS_2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Из указанных выше определения и теоремы вытекает тот факт, что при объединении кластеров их CF вектор может вычисляться инкрементно и точно. &lt;br /&gt;
Легко показать, что вычислить величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;, как и обычные метрики, также не составит труда.&lt;br /&gt;
&lt;br /&gt;
Таким образом, в данном случае информацией о кластере является не весь набор точек, а вектор CF. Хранение одного только вектора может показаться неэффективным, но этого вполне достаточно для оперирования всеми необходимыми метриками, на основе которых принимаются решения в алгоритме BIRCH.&lt;br /&gt;
&lt;br /&gt;
==== Кластерное дерево ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; &#039;&#039;&#039;Кластерное дерево (CF Tree)&#039;&#039;&#039; - это взвешенно сбалансированное дерево с двумя параметрами: &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - коэффициент разветвления, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - пороговая величина.&lt;br /&gt;
&lt;br /&gt;
Каждый нелистьевой узел дерева имеет не более чем &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; вхождений узлов следующей формы: &amp;lt;math&amp;gt;[CF_i,child_i]&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i=1,2,...,B&amp;lt;/math&amp;gt;, &#039;&#039;child&#039;&#039; - указатель на i-й дочерний узел, &amp;lt;math&amp;gt;CF_i&amp;lt;/math&amp;gt; - CF вектор соответствующего подкластера.&lt;br /&gt;
&lt;br /&gt;
Каждый листьевой узел имеет ссылку на два соседних узла (&#039;&#039;prev&#039;&#039; и &#039;&#039;next&#039;&#039;) для того, чтобы связать все узлы для эффективного сканирования.&lt;br /&gt;
Все листьевые узлы должны удовлетворять пороговому ограничению &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, т.е. диаметр (радиус) не должен превосходить &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;.&lt;br /&gt;
В процессе вставки новых данных CF дерево строится динамически. Оно использует вставку данных для кластеризации точно также как &amp;lt;math&amp;gt;B+&amp;lt;/math&amp;gt; [https://ru.wikipedia.org/wiki/B%2B-%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE дерево] использует её для поиска.&lt;br /&gt;
CF дерево очень компактно, поскольку каждый листьевой узел - это не просто точка, а подкластер (который объединяет множество точек с учётом ограничения &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Операция вставки в &#039;&#039;&#039;CF&#039;&#039;&#039; дерево ====&lt;br /&gt;
&lt;br /&gt;
Опишем алгоритм вставки элемнта &amp;lt;math&amp;gt;Ent&amp;lt;/math&amp;gt; в CF дерево:&lt;br /&gt;
&lt;br /&gt;
1) &#039;&#039;Определение подходящего листа&#039;&#039;: Начиная с корня, алгоритм рекурсивно спускается по CF дереву, выбирая &#039;&#039;&#039;ближайший&#039;&#039;&#039; дочерний узел в соответствии с выбранной метрикой &amp;lt;math&amp;gt;D0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D4&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &#039;&#039;Преобразование листа&#039;&#039;: Когда алгоритм доходит до листа, он находит ближайшую листьевой элемент, скажем, &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;, а затем проверяет, можно ли добавить &#039;&#039;Ent&#039;&#039; к &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt; без нарушения порогового условия. Если да, то с учётом этого изменяется CF вектор для &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;; если нет, то &#039;&#039;Ent&#039;&#039; становится новым элементом листа. Если в листе для этого достаточно места, то шаг окончен, иначе он должен &amp;quot;расщепиться&amp;quot;. Расщепление узла производится при помощи выбора за основу наиболее удалённой друг от друга пары элементов и перераспределение оставшихся элементов в соответствии с выбранным критерием близости.&lt;br /&gt;
&lt;br /&gt;
3) &#039;&#039;Преобразование пути к листу&#039;&#039;: После вставки &#039;&#039;Ent&#039;&#039; в лист мы должны обновить информацию о CF для каждого нелистьевого элемента на пути к листу. При отсутствии расщепления это означает простое сложение CF векторов для отражения факта добавления &#039;&#039;Ent&#039;&#039;. Расщепление листа же требует вставки нового нелистьевого элемента в родительский узел для задания только что созданного листа. Если у родителя есть место для этого элемента, то необходимо просто преобразовать CF векторы на всех более высоких уровнях. В общем случае, однако, нам также придётся расщепить родительский узел, и так далее до корня. Если расщеплён корень, то высота дерева увеличивается на единицу.&lt;br /&gt;
&lt;br /&gt;
4) &#039;&#039;Улучшение слияния&#039;&#039;: Расщепление вызвано ограничением на размер узла, который не зависит от кластеризационных свойств данных. Если во входящем потоке присутствуют &amp;quot;искажённые&amp;quot; (из областей с низкой плотностью) данные, это может повлиять на качество кластеризации, а также уменьшить эффективность использования памяти. Дополнительный шаг алгоритма помогает решить эти проблемы: предположим, что произошло расщепление листа, и распространение этого процесса остановилось на некотором нелистьевом узле &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt;, то есть &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; может вместить дополнительный элемент, полученный после расщепления. Теперь мы сканируем узел &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; для нахождения двух наиболее близких элементов. Если это не пара, отвечающая расщеплению, мы пытаемся объединить их и поставить в соответствие два дочерних узла. Если количество элементов в дочерних узлах  больше B, мы снова расщепляем результат объединения.&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;R&amp;lt;/math&amp;gt; или диаметра &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластерного элемента. Выполняется при попытке вставить новый элемент в один из подкластеров листьевого узла дерева.&lt;br /&gt;
&lt;br /&gt;
* расстояния между двумя элементами. Выполняется при поиске ближайшего по отношению к новому элементу подкластера в узле дерева по одной из рассмотренных в разд. 1.2.1 метрик &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Зная характеристики кластерных элементов &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;, в результате алгебраических преобразований можно получить следующие упрощенные формулы вычисления необходимых значений:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\vec{X_0} = \frac{\vec{LS}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{SS - 2\vec{X_0}\vec{LS} + N(\vec{X_0})^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{2(N \cdot SS - (\vec{LS})^2)}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{N_1 \cdot SS_2 + N_2 \cdot SS_1 - 2\vec{LS_1}\vec{LS_2}}{N_1 \cdot N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{2((N_1+N_2)(SS_1+SS_2)-(\vec{LS_1}+\vec{LS_2})^2)}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Реализация алгоритма BIRCH состояит из следующих четырёх фаз:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 1&#039;&#039;&#039;. Главной задачей фазы 1 является сканирование всех данных и построение в памяти исходного CF дерева, используя заданное количество памяти. Это дерево стремится отразить информацию о кластеризации данных настолько хорошо, насколько это позволяют ограничения по памяти. При этом плотно распределённые данные группируются в подкластеры, а более разрозненные данные удаляются. После завершения фазы 1 вспомогательные вычисления в дальнейших фазах будут:&lt;br /&gt;
&lt;br /&gt;
1) быстрее, потому что (а) больше не нужны операции ввода-вывода, (b) проблема кластеризации начальных данных упрощается до проблемы кластеризации подкластеров в листьях;&lt;br /&gt;
&lt;br /&gt;
2) точнее, потому что (а) большинство данных с низкой плотностью удалены, (b) оставшиеся данные распределены оптимально (в соответствии с доступным количеством памяти);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 2&#039;&#039;&#039;. Данная фаза является опциональной. Известно, что существующие методы глобальной кластеризации, используемые в рамках фазы 3, имеют различные диапазоны входных значений, при которых их реализация наиболее эффективна. Поэтому потенциально существует пробел между размером фазы 1 и входными значениями фазы 3. И фаза 2 как раз является недостающим связующим звеном: так же как и фаза 1, она сканирует листьевые элементы начального CF дерева для того, чтобы построить меньшее дерево, удаляя ещё больше элементов с низкой плотностью и группируя переполненные подкластеры в большие кластеры.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 3&#039;&#039;&#039;. В данной фазе для листьевых элементов применяется (любой подходящий) алгоритм глобальной кластеризации. Существующие алгоритмы кластеризации наборов точек могут также работать с наборами подкластеров, каждый из которых представлен своим CF вектором. Зная CF вектор, можно вычислить центроид и в дальнейшем заменить всю информацию о кластере этим значением (этого достаточно для вычисления большинства необходимых метрик). После фазы 3 мы получаем набор кластеров, который отражает основные характеристики распределяемых данных.&lt;br /&gt;
Однако, всё ещё могут оставаться некоторые неточности, для устранения которых существует фаза 4.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 4&#039;&#039;&#039;. Данная фаза является опциональной и влечёт за собой затраты на дополнительное сканирование данных для корректировки неточностей и дальнейшего улучшения кластеризации. Фаза 4 использует центроиды кластеров, полученные в фазе 3 для как основы и перераспределяет точки входных данных в ближайшие для них основы для получения нового списка кластеров. Фаза 4, если это необходимо пользователю, может быть расширена дополнительными проходами для уверенности в том, что результат приближается к оптимальному.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Последовательную реализацию основных операций алгоритма BIRCH можно продемонстрировать на примере следующего фрагмента кода на языке C++:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot;&amp;gt;&lt;br /&gt;
void CF_Node::insert(const CF_Cluster &amp;amp;entry)&lt;br /&gt;
{&lt;br /&gt;
    //Находим ближайший к новому элементу подкластер в узле&lt;br /&gt;
    СF_Vector_it closest = entry.findClosest(subclusters);&lt;br /&gt;
    //Если узел пустой, добавляем в него новый подкластер&lt;br /&gt;
    if (closest == subclusters.end()) {&lt;br /&gt;
        subclusters.push_back(entry);&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    closest-&amp;gt;add(entry);&lt;br /&gt;
    //Если узел является листьевым, и ближайший подкластер не может вместить&lt;br /&gt;
    //новый элемент, добавляем в узел новый подкластер&lt;br /&gt;
    if (leaf) {&lt;br /&gt;
        if (closest-&amp;gt;D &amp;gt; threshold) {&lt;br /&gt;
            closest-&amp;gt;remove(entry);&lt;br /&gt;
            subclusters.push_back(entry);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else {&lt;br /&gt;
        CF_Node *node = closest-&amp;gt;child;&lt;br /&gt;
        node-&amp;gt;insert(entry);&lt;br /&gt;
        //Если при добавлении нового элемента в дочерний узел тот переполнился,&lt;br /&gt;
        //расщепляем его        &lt;br /&gt;
        if (node-&amp;gt;getSubclusters().size() &amp;gt; bFactor) {&lt;br /&gt;
            CF_Vector newClusters = node-&amp;gt;splitNode();&lt;br /&gt;
            delete node;&lt;br /&gt;
            subclusters.erase(closest);&lt;br /&gt;
            subclusters.insert(subclusters.end(), newClusters.begin(), newClusters.end());&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    //Если узел является корневым и он переполнен, расщепляем его&lt;br /&gt;
    if (root &amp;amp;&amp;amp; subclusters.size() &amp;gt; bFactor) {&lt;br /&gt;
        subclusters = splitNode();&lt;br /&gt;
        leaf = false;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
CF_Vector CF_Node::splitNode()&lt;br /&gt;
{&lt;br /&gt;
    if (subclusters.size() &amp;lt; 2)&lt;br /&gt;
        return (root) ? subclusters : CF_Vector{CF_Cluster(this)};&lt;br /&gt;
    //Находим пару наиболее удаленных друг от друга подкластеров&lt;br /&gt;
    CF_Vector_it pole1, pole2;&lt;br /&gt;
    data_t longestDist = 0.0;&lt;br /&gt;
    for (auto lhs = subclusters.begin(); lhs != subclusters.end() - 1; ++lhs) {&lt;br /&gt;
        for (auto rhs = lhs + 1; rhs != subclusters.end(); ++rhs) {&lt;br /&gt;
            auto distance = getDistance(*lhs, *rhs);&lt;br /&gt;
            if (distance &amp;gt; longestDist) {&lt;br /&gt;
                longestDist = distance;&lt;br /&gt;
                pole1 = lhs;&lt;br /&gt;
                pole2 = rhs;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    //Разделяем множество всех подкластеров узла на две части&lt;br /&gt;
    CF_Vector subclusters1, subclusters2;&lt;br /&gt;
    for (auto it = subclusters.begin(); it != subclusters.end(); ++it) {&lt;br /&gt;
        if (getDistance(*it, *pole1) &amp;lt; getDistance(*it, *pole2))&lt;br /&gt;
            subclusters1.push_back(*it);&lt;br /&gt;
        else&lt;br /&gt;
            subclusters2.push_back(*it);&lt;br /&gt;
    }&lt;br /&gt;
    //Создаем два новых узла&lt;br /&gt;
    CF_Node *node1 = new CF_Node(threshold, bFactor, count, leaf, subclusters1),&lt;br /&gt;
            *node2 = new CF_Node(threshold, bFactor, count, leaf, subclusters2);&lt;br /&gt;
    //Связываем листья&lt;br /&gt;
    if (leaf) {&lt;br /&gt;
        if (prevLeaf) {&lt;br /&gt;
            node1-&amp;gt;setPrevLeaf(prevLeaf);&lt;br /&gt;
            prevLeaf-&amp;gt;setNextLeaf(node1);&lt;br /&gt;
        }&lt;br /&gt;
        if (nextLeaf) {&lt;br /&gt;
            node2-&amp;gt;setNextLeaf(nextLeaf);&lt;br /&gt;
            nextLeaf-&amp;gt;setPrevLeaf(node2);&lt;br /&gt;
        }&lt;br /&gt;
        node1-&amp;gt;setNextLeaf(node2);&lt;br /&gt;
        node2-&amp;gt;setPrevLeaf(node1);&lt;br /&gt;
    }&lt;br /&gt;
    CF_Cluster cluster1(node1), cluster2(node2);&lt;br /&gt;
    return CF_Vector{cluster1, cluster2};&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Для начала проанализируем вычислительную сложность фазы 1.&lt;br /&gt;
Максимальный размер дерева &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt; - ограничение по памяти на размер узла, а &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - общий объем памяти. Для того чтобы вставить элемент, мы должны пройти путь от корня до листа (это около &amp;lt;math&amp;gt;1+log_B\frac{M}{P}&amp;lt;/math&amp;gt; узлов). В каждом узле в поисках &amp;quot;ближайшего&amp;quot; нам необходимо просмотреть B элементов; сложность для каждого элемента пропорциональна размерности &#039;&#039;d&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Поэтому сложность вставки всех входных точек &amp;lt;math&amp;gt;O(d \cdot N \cdot B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В случае, когда необходимо перестроить дерево, предположим, что ES - это размер CF элемента. Существует максимум &amp;lt;math&amp;gt;\frac{M}{ES}&amp;lt;/math&amp;gt; листьевых элементов для вставки, поэтому сложность повторной вставки листьевых элементов &amp;lt;math&amp;gt;O(d \cdot \frac{M}{ES} \cdot B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Количество итераций перестройки дерева зависит от пороговой величины. На самом деле, это около &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; (двоичное основание появилось из-за того, что мы не можем провести оценку более чем в 2 раза отличающуюся от текущего размера). &amp;lt;math&amp;gt;N_0&amp;lt;/math&amp;gt; - это число входных точек, загруженных в память с пороговым ограничением &amp;lt;math&amp;gt;T_0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Соответственно, итоговая сложность фазы 1 &amp;lt;math&amp;gt;O(d \cdot N \cdot B(1+log_B\frac{M}{P})+log_2\frac{N}{N_0} \cdot d \cdot \frac{M}{ES} \cdot B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Анализ фазы 2 проводится аналогично.&lt;br /&gt;
&lt;br /&gt;
Что касается операций ввода-вывода, то в фазе 1 данные сканируются один раз, а в фазе 2 не сканируются вовсе.&lt;br /&gt;
Некоторое количество вычислений связано с удалением точек из областей с низкой плотностью.&lt;br /&gt;
Если количество доступной для этой операции памяти не больше &#039;&#039;M&#039;&#039; и проведено порядка &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; перестроек дерева, то сложность ввода-вывода для фазы 1 существенно не отличается от сложности чтения из файла. Основываясь рассуждениях выше, сложность фаз 1 и 2 будет линейно увеличиваться с ростом N.&lt;br /&gt;
&lt;br /&gt;
В фазе 3 нет операций ввода-вывода. Её сложность ограничена константой, которая зависит от максимального размера входных данных, и варианта выбранного алгоритма для кластеризации. &lt;br /&gt;
&lt;br /&gt;
Фаза 4 снова сканирует данные и записывает каждую точку в подходящий кластер; время работы пропорционально &amp;lt;math&amp;gt;N \cdot K&amp;lt;/math&amp;gt;.   &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&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;D_2=\frac{N_1\cdot SS_2+N_2\cdot SS_1-2 \cdot \vec{LS_1}\cdot \vec{LS_2}}{N_1\cdot N_2}&amp;lt;/math&amp;gt;, где&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF_1=[N_1,\vec{LS_1},SS_1]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF_2=[N_2,\vec{LS_2},SS_2]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:ZgYL51QJsQk.jpg|600px|thumb|center]]&lt;br /&gt;
&lt;br /&gt;
=== Поиск ближайшего подкластера ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;E&amp;lt;/math&amp;gt; - новый элемент&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF_i, i = 1,...,B&amp;lt;/math&amp;gt; - подкластеры узла&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - операция min&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\rho&amp;lt;/math&amp;gt; - нахождение расстояния&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:PFA16KHUQ3I.jpg|600px|thumb|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Скалярное произведение ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;s = \vec{x}\cdot\vec{y}=\sum_{i=1}^d x_i\cdot y_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Xb7FYXVMPpQ.jpg|600px|thumb|center]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&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;\vec{LS},\vec{X0}, R, D, D_0-D_4&amp;lt;/math&amp;gt;, в процессе чего выполняются операции сложения и скалярного произведения векторов.&lt;br /&gt;
&lt;br /&gt;
Таким образом, параллельная сложность фазы 1 алгоритма будет равна &amp;lt;math&amp;gt;O((N + log_2\frac{N}{N_0} \cdot \frac{M}{ES})(log_2 B + log_2 d)(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Другим способом параллелизации алгоритма может служить создание и заполнение сразу множества кластерных деревьев, между которыми будут распределены входные данные. Множество всех подкластеров листьевых узлов полученных таким образом деревьев может быть подвергнуто глобальной кластеризации с помощью какого-либо из известных параллельных алгоритмов, например, k-средних&amp;lt;ref&amp;gt;[A Garg, N Gupta PBIRCH: A Scalable Parallel Clustering algorithm for Incremental Data //10th International Database Engineering and Applications Symposium (IDEAS&#039;06), 2006&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; набор из &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек &amp;lt;math&amp;gt;\{X_i\}, i=1,...,N&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем входных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;N \cdot d&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; кластерное дерево с не более чем &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt; узлами.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительная мощность алгоритма имеет порядок &amp;lt;math&amp;gt;O(\frac{d \cdot B \cdot (1+log_B\frac{M}{P}) \cdot (N +log_2\frac{N}{N_0} \cdot \frac{M}{ES})}{N \cdot d + M})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм BIRCH не является детерминированным, так как процесс его выполнения во многом зависит от входных данных.&lt;br /&gt;
&lt;br /&gt;
К достоинствам алгоритма можно отнести следующие его свойства:&lt;br /&gt;
&lt;br /&gt;
1. BIRCH является локальным алгоритмом, то есть каждое решение о каждом элементе кластера принимается без повторного сканирования данных или уже существующих кластеров. Используются только метрики, отражающие близость элементов друг к другу.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH использует факт неравномерного распределения данных в пространстве и поэтому не все данные рассматриваются как одинаково важные для построения кластера. Области с большой плотностью обрабатываются как единый кластер. Данные в более разреженных областях могут удаляться (опционально).&lt;br /&gt;
&lt;br /&gt;
3. BIRCH использует всю доступную память для получения наилучших из возможных подкластеров, в то же время минимизируя затраты на операции ввода/вывода. Оптимизация процесса кластеризации достигается за счет использования взвешенно-сбалансированного дерева. При этом время исполнения линейно.&lt;br /&gt;
&lt;br /&gt;
4. BIRCH не требует всего набора данных заранее (при этом просматривает его всего один раз).&lt;br /&gt;
&lt;br /&gt;
В свою очередь, недостатки алгоритма можно сформулировать следующим образом:&lt;br /&gt;
&lt;br /&gt;
1. Алгоритм позволяет работать только с числовыми данными.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH хорошо выделяет только кластеры сферической формы.&lt;br /&gt;
&lt;br /&gt;
3. Существует необходимость в задании пороговых значений.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
Проведём исследование масштабируемости параллельной реализации алгоритма BIRCH. Исследование проводилось на суперкомпьютере &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;
[[file:Масштабируемость параллельной реализации алгоритма BIRCH. Производительность.png|thumb|center|700px|Рисунок 1. График времени работы параллельной реализации алгоритма BIRCH. ]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[file:Масштабируемость параллельной реализации алгоритма BIRCH. Эффективность.png|thumb|center|700px|Рисунок 2. График эффективности распараллеливания алгоритма BIRCH относительно последовательной реализации. ]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Набор изменяемых параметров запуска реализации алгоритма и границы значений параметров алгоритма: &lt;br /&gt;
*	число процессоров [8 : 80] с шагом 8&lt;br /&gt;
*	число точек [100 000 : 1 000 000] с шагом 100 000&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В результате проведённых экспериментов был получен следующий диапазон эффективности реализации алгоритма:&lt;br /&gt;
*	минимальная эффективность реализации 9,13% (80 процессоров, 100 000 точек)&lt;br /&gt;
*	максимальная эффективность реализации 235,42% (8 процессоров, 800 000 точек)&lt;br /&gt;
&lt;br /&gt;
Полученные результаты могут быть объяснены недерминированностью алгоритма BIRCH и существенной зависимостью времени его работы от входных данных.&lt;br /&gt;
&lt;br /&gt;
Оценка масштабируемости параллельной реализации:&lt;br /&gt;
*	По числу процессов:  при увеличении числа процессов эффективность распараллеливания снижается. При количестве процессов &amp;lt;math&amp;gt;n&amp;gt;30&amp;lt;/math&amp;gt; темп снижения становится несущественным.&lt;br /&gt;
* По размеру задачи: при увеличении размера входных данных эффективность растет неравномерно, что свидетельствует о сложной зависимости от входных данных.&lt;br /&gt;
&lt;br /&gt;
Для исследования возможностей паралеллизма алгоритма BIRCH была написана [https://github.com/duran-duran/birch реализация на языке C++] с использованием технологии MPI. В данной реализации входные данные равномерно распределяются между всеми процессами, в каждом из которых выполняется построение собственного кластерного дерева. Листьевые элементы полученных деревьев затем подвергаются глобальной кластеризации с помощью распределенного алгоритма k-средних. В качестве входных данных использовались точки размерности &amp;lt;math&amp;gt;d=5&amp;lt;/math&amp;gt;, координаты которых были равномерно распределены в диапазоне &amp;lt;math&amp;gt;[-10000;10000]&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable mw-collapsible mw-collapsed&amp;quot;&lt;br /&gt;
! Технические детали реализации&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
Компилятор: intel/15.0.090&lt;br /&gt;
&lt;br /&gt;
Версия реализации MPI: openmpi/1.10.2-icc&lt;br /&gt;
&lt;br /&gt;
Планировщик задач: slurm/2.5.6&lt;br /&gt;
&lt;br /&gt;
Очереди: test, regular4&lt;br /&gt;
&lt;br /&gt;
Команда компиляции: mpicxx -std=c++11 -Wall &amp;lt;source_files&amp;gt; -o &amp;lt;executable&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Команда запуска: sbatch -n &amp;lt;num_of_processes&amp;gt; -p &amp;lt;queue&amp;gt; -o &amp;lt;log_file&amp;gt; ompi &amp;lt;executable&amp;gt; &amp;lt;args&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;
* [http://scikit-learn.org/stable/modules/generated/sklearn.cluster.Birch.html scikit-learn]&lt;br /&gt;
* [http://cucis.ece.northwestern.edu/projects/DMS/MineBench.html NU-MineBench]&lt;br /&gt;
Пользовательские реализации:&lt;br /&gt;
* [https://code.google.com/archive/p/jbirch/ JBIRCH]&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Coctic</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9C%D0%BE%D1%80%D0%BE%D0%B7%D0%BE%D0%B2%D0%B0&amp;diff=20815</id>
		<title>Обсуждение участника:Светлана Морозова</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9C%D0%BE%D1%80%D0%BE%D0%B7%D0%BE%D0%B2%D0%B0&amp;diff=20815"/>
		<updated>2016-12-13T14:43:45Z</updated>

		<summary type="html">&lt;p&gt;Coctic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Статья [[Участник:Smirnov.maxim/BIRCH]] ==&lt;br /&gt;
&lt;br /&gt;
=== Неправильная структура статьи ===&lt;br /&gt;
* Слово &amp;quot;Часть&amp;quot; в заголовках лишнее [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 17:55, 21 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:01, 31 октября 2016 (MSK)&lt;br /&gt;
* Название пункта 1.3 не из шаблона [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 17:55, 21 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:01, 31 октября 2016 (MSK)&lt;br /&gt;
* Пункты 1.4-1.5 должны быть 1.3-1.4 [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 17:55, 21 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:01, 31 октября 2016 (MSK)&lt;br /&gt;
* Пункты 3.1 шаблоном не предусмотрен [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 17:55, 21 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:01, 31 октября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
=== Отсутствующие части ===&lt;br /&gt;
* Отсутствует указание автора [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 17:55, 21 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:01, 31 октября 2016 (MSK)&lt;br /&gt;
* Нет пунктов 1.5-1.10, 2.7  [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 17:55, 21 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:01, 31 октября 2016 (MSK)&lt;br /&gt;
* В тексте есть ссылки на 2 рисунка, которых нет [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 17:55, 21 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:01, 31 октября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
=== Замечания по тексту ===&lt;br /&gt;
* Пункт 1.3: есть указание на &amp;quot;фазу 1&amp;quot;, нет описания  дальнейших фаз [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 17:55, 21 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:01, 31 октября 2016 (MSK)&lt;br /&gt;
* Пункт 1.3: названия подпунктов &amp;quot;фаза 1&amp;quot;, &amp;quot;уменьшаемость&amp;quot;, &amp;quot;пороговые значения&amp;quot;, &amp;quot;достоинства алгоритма&amp;quot; не выглядят логическими частями описания алгоритма [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 17:55, 21 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:01, 31 октября 2016 (MSK)&lt;br /&gt;
* В разделе &amp;quot;Литература&amp;quot; единственная ссылка на Википедию, причем на на конкретную страницу, а на Википедию вообще (причем ссылка не ведет никуда, это просто текст). Фактически список литературы отсутствует. [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 17:55, 21 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:01, 31 октября 2016 (MSK)&lt;br /&gt;
--------------------------&lt;br /&gt;
* в списке авторов не указан вклад каждого автора [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:01, 31 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:51, 7 ноября 2016 (MSK)&lt;br /&gt;
* п. 1.8 не приведена оценка параллельной сложности алгоритма [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:01, 31 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:51, 7 ноября 2016 (MSK)&lt;br /&gt;
* п. 1.9 не приведены оценки объема входных и выходных данных [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:01, 31 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:51, 7 ноября 2016 (MSK)&lt;br /&gt;
* п. 1.10 не приведена оценка вычислительной мощности алгоритма [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:01, 31 октября 2016 (MSK)&lt;br /&gt;
** Не исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:51, 7 ноября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 16:51, 16 ноября 2016 (MSK)&lt;br /&gt;
* в списке литературы у ссылок отсутствуют выходные данные, позволяющие их однозначно идентифицировать [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:01, 31 октября 2016 (MSK)&lt;br /&gt;
** Исправлено частично. Ссылка 1 по-прежнему не имеет достаточного количества выходных данных [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:51, 7 ноября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 16:51, 16 ноября 2016 (MSK)&lt;br /&gt;
* Отсутствует п. 2.4. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 16:51, 16 ноября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:57, 12 декабря 2016 (MSK)&lt;br /&gt;
* Необходимо указать характеристики программно-аппаратной платформы (какой компилятор, с какими опциями использовался, какие версии библиотек, на каких узлах проводился запуск и т.д.) [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:57, 12 декабря 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 17:43, 13 декабря 2016 (MSK)&lt;/div&gt;</summary>
		<author><name>Coctic</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:%D0%A8%D0%B8%D1%88%D0%BA%D0%BE%D0%B2_%D0%98%D0%BB%D1%8C%D1%8F_%D0%A1%D0%B5%D1%80%D0%B3%D0%B5%D0%B5%D0%B2%D0%B8%D1%87/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_HCM_(Hard_C_%E2%80%93_Means)&amp;diff=20814</id>
		<title>Участник:Шишков Илья Сергеевич/Алгоритм HCM (Hard C – Means)</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:%D0%A8%D0%B8%D1%88%D0%BA%D0%BE%D0%B2_%D0%98%D0%BB%D1%8C%D1%8F_%D0%A1%D0%B5%D1%80%D0%B3%D0%B5%D0%B5%D0%B2%D0%B8%D1%87/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_HCM_(Hard_C_%E2%80%93_Means)&amp;diff=20814"/>
		<updated>2016-12-13T14:42:33Z</updated>

		<summary type="html">&lt;p&gt;Coctic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Алгоритм HCM (Hard C – Means)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(ncK)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(cK)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;O(nK)&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;O(c(K+n))&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Основные авторы описания: [[Участник:Шишков_Илья_Сергеевич|Илья Шишков]] (1.1-1.4, 2.7), [[Участник:Темербекова_Гульгайша|Гульгайша Темербекова]] (1.5-1.10, 3)&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Алгоритм HCM (Строгий алгоритм С-средних) был предложен группой исследователей(Jang, Sun and Mizutani) в 1997 и относится к классу алгоритмов со строгой кластеризаций. &lt;br /&gt;
&lt;br /&gt;
Кластеризацией называется подход к описанию данных, в котором наиболее схожие данные объединяются в группы(кластеры). Кластеризация является распространенным подходом для анализа данных и используется во многих сферах научной деятельности, таких как машинное обучение, анализ данных, распознавание шаблонов, анализ изображений и биоинформатика.&lt;br /&gt;
&lt;br /&gt;
Кластеризация представляет собой комбинирование рассматриваемых объектов так, чтобы каждая группа объектов обладала схожим свойством. В общем случае кластеризация характеризуются следующими критериями:&lt;br /&gt;
- Каждая группа или кластер однородны; объекты, принадлежащие одной группе имеют схожие свойства;&lt;br /&gt;
- Каждая группа или кластер отличаются от других кластеров т.е. объекты, принадлежащие одному кластеру, должны отличатся от объектов других кластеров&lt;br /&gt;
&lt;br /&gt;
В строгой кластеризации наборы данных разделяются на кластеры однозначно. Каждый набор данных может относится только к одному кластеру. &lt;br /&gt;
Строгой кластеризации характеризуется следующими свойствами:&lt;br /&gt;
- Используется для классификации данных в однозначные наборы&lt;br /&gt;
- Каждый набор данных принадлежит только одному кластеру&lt;br /&gt;
- Кластеры также называют разделами&lt;br /&gt;
- Результатом работы кластерного алгоритма является матрица соответствия которая показывает, к какому кластеру принадлежит каждый набор данных&lt;br /&gt;
&lt;br /&gt;
В этом кластерном алгоритме не допускается частичное отношение к кластеру (как в FCM). HCM предназначен для классификации входных наборов в строгом смысле. В строгом алгоритме С-средних данные классифицируются по кластерам однозначно, т.е. при определенном заранее критерии, каждый элемент данных может принадлежать одному и только одному кластеру. &lt;br /&gt;
&lt;br /&gt;
Алгоритм HCM является итеративным и состоит из нескольких шагов: &lt;br /&gt;
&lt;br /&gt;
1.&#039;&#039;&#039;Инициализация: &#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Случайным образом определяются C векторов - центров кластеров&lt;br /&gt;
&lt;br /&gt;
2. &#039;&#039;&#039;Расчет рядовой матрицы:&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
В процессе расчета рядовой матрицы каждый вектор сравнивается с ближайшим кластерным центром&lt;br /&gt;
&lt;br /&gt;
3. &#039;&#039;&#039;Расчет оценочной функции:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Проверка условия, при котором алгоритм завершает работу и вывод результата в этом случае&lt;br /&gt;
&lt;br /&gt;
4. &#039;&#039;&#039;Переопределение кластерных центров&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Пункты 2-4 выполняются до тех пор, пока в пункте 3 проверка не станет успешной.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма &amp;lt;ref&amp;gt;Arabinda Panda &amp;amp; Satchidananda Dehuri. Hard C-means Clustering Algorithm in Gene Expression Data // International Journal on Advanced Computer Theory and Engineering, ISSN-PRINT: 2319-2526. - 2013. - v. 2. - p. 35-39 [http://www.irdindia.in/journal_ijacte/pdf/vol2_iss1/8.pdf]&amp;lt;/ref&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Обозначения&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;U&amp;lt;/math&amp;gt; - наборы данных&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;u_{i}&amp;lt;/math&amp;gt; - i-ый набор из &amp;lt;math&amp;gt;U&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;u&amp;lt;/math&amp;gt; - любой набор из &amp;lt;math&amp;gt;U&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; - количество наборов в &amp;lt;math&amp;gt;U&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c_{j}&amp;lt;/math&amp;gt; - j-ый кластер&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c_{j}&amp;lt;/math&amp;gt; - j-ый кластерный центр&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;c^*_{j}&amp;lt;/math&amp;gt; - j-ый кластерный центр после обновления&lt;br /&gt;
&lt;br /&gt;
Выходные данные: &lt;br /&gt;
&amp;lt;math&amp;gt;c^*_{1}, c^*_{2}, ... c^*_{c}, M&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Объектная функция:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;J=\sum_{j = 1}^{c} \sum_{u_{i} \in C_{j}}^{} \|u_{i}-c_{j}\|^2,  j \in 1,2, ... c, i={1,2, ...K}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 1&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Из входного набора &amp;lt;math&amp;gt;u_{1},u_{2}, ... u_{n}&amp;lt;/math&amp;gt; выбираются &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; начальных кластерных центра &amp;lt;math&amp;gt; c_{1},c_{2},...,c_{c}&amp;lt;/math&amp;gt;либо случайным образом, либо с использованием заранее определенного алгоритма&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 2&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Рассчитывается рядовая матрица &amp;lt;math&amp;gt; M=\|m_{ik}\|&amp;lt;/math&amp;gt; каждый элемент которой вычисляется по следующей формуле: &lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ik} = \begin{cases}&lt;br /&gt;
1, &amp;amp; \|u_k-c_i\|^2 \leqslant \|u_k-c_j\|^2 \;\; \text{for all } i \neq j; \;\; (i,j=1,2,\ldots,c; \; k = 1,2,\ldots,K)\\&lt;br /&gt;
0, &amp;amp; \text{other}.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 3&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Рассчитывается объектная функция J. На этом этапе может быть инициировано завершение алгоритма в случае если значение объектной функции незначительно изменилось относительно предыдущей итерации или достигло ожидаемого значения. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 4&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Рассчитываются новые кластерные центры по следующей формуле: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; c^*_{j} = \frac{1}{|C_{j}|} \sum_{u_{i} \in C_{j}}^{} c_{i}, j=1,2,3..,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;|C_{j}| &amp;lt;/math&amp;gt; - число элементов, принадлежащих кластеру &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 5&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Если алгоритм не завершил свою работу на шаге 3 то переходим к шагу 2.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром данного алгоритма является вычисление на каждой итерации алгоритма квадратов норм между кластерными центрами и векторами из входного набор согласно формуле &amp;lt;math&amp;gt;\|u_k-c_i\|^2&amp;lt;/math&amp;gt;. На каждой итерации алгоритма происходит &amp;lt;math&amp;gt;cK&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;&lt;br /&gt;
\|u_k-c_i\|^2&lt;br /&gt;
&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;J=\sum_{j = 1}^{c} \sum_{u_{i} \in C_{j}}^{} \|u_{i}-c_{j}\|^2,  j \in 1,2, ... c, i={1,2, ...K}&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; c^*_{j} = \frac{1}{|C_{j}|} \sum_{u_{i} \in C_{j}}^{} u_{i}, j=1,2,3..,c&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Последовательность исполнения метода следующая &amp;lt;ref&amp;gt; Jyh-Shing Roger Jang, Chuen-Tsai Sun, Eiji Mizutani. Neuro-fuzzy and soft computing: a computational approach to learning and machine intelligence. Prentice-Hall, Inc. Simon &amp;amp; Schuster/A Viacom Company Upper Saddle River, NJ 07458. - 1997. - p. 424. [http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf]&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
1. Инициализация кластерных центров &amp;lt;math&amp;gt;c_i \, (i=1,2,\ldots,c)&amp;lt;/math&amp;gt;. Это можно сделать выбрав случайным образом &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; – векторов из входного набора. &lt;br /&gt;
&lt;br /&gt;
2. Вычисление рядовой матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ik} = \begin{cases}&lt;br /&gt;
1, &amp;amp; \|u_k-c_i\|^2 \leqslant \|u_k-c_j\|^2 \;\; \text{for all } i \neq j; \;\; (i,j=1,2,\ldots,c; \; k = 1,2,\ldots,K) \\&lt;br /&gt;
0, &amp;amp; \text{other}.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&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;&lt;br /&gt;
\sum\limits_{i=1}^c m_{ij} = 1, \;\; \sum\limits_{j=1}^K m_{ij} = K.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3. Расчёт объектной функции:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^c J_i = \sum\limits_{i=1}^c \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right)&lt;br /&gt;
.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На этом шаге происходит остановка и выход из цикла, если полученное значение ниже пороговой величины или полученное значение не сильно отличается от значений, полученных на предыдущих циклах.&lt;br /&gt;
&lt;br /&gt;
4. Пересчёт кластерных центров выполняется в соответствии со следующим уравнением:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;|C_i|&amp;lt;/math&amp;gt; подразумевается количество элементов в &amp;lt;math&amp;gt;i&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;n&amp;lt;/math&amp;gt; вычитаний, &amp;lt;math&amp;gt;n-1&amp;lt;/math&amp;gt; сложений  и &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; операций возведения в квадрат (умножений).&lt;br /&gt;
&lt;br /&gt;
Для каждой итерации алгоритма требуется:&lt;br /&gt;
* &amp;lt;math&amp;gt;ncK&amp;lt;/math&amp;gt; умножений,&lt;br /&gt;
* &amp;lt;math&amp;gt;ncK&amp;lt;/math&amp;gt; вычитаний,&lt;br /&gt;
* &amp;lt;math&amp;gt;K(cn+1)&amp;lt;/math&amp;gt; сложений,&lt;br /&gt;
* &amp;lt;math&amp;gt;K(c-1)&amp;lt;/math&amp;gt; сравнений.&lt;br /&gt;
&lt;br /&gt;
Умножения, сложения (вычитания), сравнения составляют &#039;&#039;основную часть алгоритма&#039;&#039;.&lt;br /&gt;
 &lt;br /&gt;
Итоговая сложность последовательной реализации алгоритма &amp;lt;math&amp;gt;O(ncK)&amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt; Pawan Kumar, Mr. Pankaj Verma, Rakesh Sharma. Comparative analysis of Fuzzy C-mean and Hard C-mean algorithm // International Journal of information Technology and Knowledge Management. - July-December 2010. - v. 2 [http://csjournals.com/IJITKM/PDF%203-1/39.pdf]&amp;lt;/ref&amp;gt;. Обычно &amp;lt;math&amp;gt;n&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;
=== Информационный граф ===&lt;br /&gt;
опишем граф как аналитически, так и в виде рисунка. &lt;br /&gt;
&lt;br /&gt;
Граф алгоритма состоит из пяти групп вершин.&lt;br /&gt;
 &lt;br /&gt;
&#039;&#039;&#039;Первая&#039;&#039;&#039; группа вершин &#039;&#039;&#039;&#039;&#039;&amp;lt;math&amp;gt;c_1,...,c_c&amp;lt;/math&amp;gt;&#039;&#039;&#039;&#039;&#039; - прямое вычисление расстояния до кластерных центров, то есть вычисление расстояний от заданного элемента &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; до каждого из кластерных центров.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вторая&#039;&#039;&#039; группа вершин &#039;&#039;&#039;&#039;&#039;min&#039;&#039;&#039;&#039;&#039; - ей соответствует вычисление минимального расстояния до кластерных центров,передача найденного минимального расстояния и соответствующего ему индекса кластера.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Третья&#039;&#039;&#039; группа вершин &#039;&#039;&#039;&#039;&#039;M&#039;&#039;&#039;&#039;&#039; - ей соответствует операция записи единички в столбец матрицы.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Четвертая&#039;&#039;&#039; группа вершин &#039;&#039;&#039;&#039;&#039;J&#039;&#039;&#039;&#039;&#039; - вычисление объектной функции, происходит проверка условия достижения необходимой точности, если достигли заданной точности то переход в &#039;&#039;&#039;&#039;&#039;Out&#039;&#039;&#039;&#039;&#039;, в противном случае &#039;&#039;&#039;&#039;&#039;Conversion&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Пятая&#039;&#039;&#039; группа вершин &#039;&#039;&#039;&#039;&#039;Conversion&#039;&#039;&#039;&#039;&#039; - пересчёт кластерных центров и переход на следующую итерацию.&lt;br /&gt;
&lt;br /&gt;
На рисунке изображена одна итерация алгоритма.&lt;br /&gt;
 &lt;br /&gt;
[[File:Picture.png|thumb|600px|center|Рисунок 1. &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; - входные данные, &#039;&#039;&#039;&#039;&#039;&amp;lt;math&amp;gt;c_1,...,c_c&amp;lt;/math&amp;gt;&#039;&#039;&#039;&#039;&#039; - вычисление расстояния до кластерных центров и значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; единое для каждой группы &#039;&#039;&#039;&#039;&#039;&amp;lt;math&amp;gt;c_1,...,c_c&amp;lt;/math&amp;gt;&#039;&#039;&#039;&#039;&#039;, &#039;&#039;&#039;&#039;&#039;min&#039;&#039;&#039;&#039;&#039; - нахождение минимального расстояния до кластерных центров, &#039;&#039;&#039;&#039;&#039;M&#039;&#039;&#039;&#039;&#039; - запись единички в столбец матрицы, &#039;&#039;&#039;&#039;&#039;J&#039;&#039;&#039;&#039;&#039; - расчёт объектной функции, &#039;&#039;&#039;&#039;&#039;Conversion&#039;&#039;&#039;&#039;&#039; — пересчёт кластерных центров, &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для одной итерации алгоритма в параллельном варианте требуется &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; раз последовательно выполнить для каждого &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; следующие ярусы:&lt;br /&gt;
* &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; операций нахождения расстояния от элемента &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; до каждого из кластерных центров.&lt;br /&gt;
* &amp;lt;math&amp;gt;C-1&amp;lt;/math&amp;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;u_i&amp;lt;/math&amp;gt;. Расчёт значения объектной функции &amp;lt;math&amp;gt;J&amp;lt;/math&amp;gt; сложно представить в параллельном варианте, поэтому вычисление объектной функции производится последовательно.Использование параллельной реализации алгоритма приведёт к понижению производительности при небольшой размерности системы и малом объеме выборки. При параллельном варианте необходима пересылка данных, что при малом объеме выборки и небольшой размерности займет больше времени, чем при последовательном варианте.&lt;br /&gt;
Как легко видеть из информационного графа, высота [[глоссарий#Ярусно-параллельная форма графа алгоритма|ЯПФ]] составляет &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;, ширина ЯПФ составляет &amp;lt;math&amp;gt;O(cK)&amp;lt;/math&amp;gt;, если число итераций меньше объема выборки.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; &lt;br /&gt;
# &amp;lt;math&amp;gt;\{u_k\}_{k=1}^{K}&amp;lt;/math&amp;gt; — исходный набор векторов, принадлежащие пространству &amp;lt;math&amp;gt;\mathbb{R}^n&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;nK&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
# &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; — матрица, принадлежащая пространству &amp;lt;math&amp;gt;\mathbb{R}^{c \times K}&amp;lt;/math&amp;gt;.&lt;br /&gt;
# &amp;lt;math&amp;gt;\{c^*_i\}_{i=1}^{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+n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Назначение:&#039;&#039;&#039; кластеризация больших наборов числовых данных. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Достоинства:&#039;&#039;&#039; легкость реализации,вычислительная простота.&lt;br /&gt;
 &lt;br /&gt;
&#039;&#039;&#039;Недостатки:&#039;&#039;&#039; задание количества кластеров,отсутствие гарантии в нахождении оптимального решения.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
Проведём исследование масштабируемости параллельной реализации алгоритма Hard C - Means (HCM). Исследование проводилось на суперкомпьютере &amp;quot;Ломоносов&amp;quot; [http://parallel.ru/cluster Суперкомпьютерного комплекса Московского университета] с пиковой производительностью 1,7 Пфлопс, число процессоров/ядер x86: 12 346 / 52 168. Программа написана на языке C с использованием [http://hpc.cmc.msu.ru/bgp/development/parallel MPI], не использовалось дополнительных опций. Использовалась следующая [https://github.com/cNikolaou/mpi-kmeans параллельная реализация алгоритма HCM].&lt;br /&gt;
&lt;br /&gt;
Набор и границы значений изменяемых [[Глоссарий#Параметры запуска|параметров запуска]] реализации алгоритма: &lt;br /&gt;
&lt;br /&gt;
*	число ядер &amp;lt;math&amp;gt;[16 : 256]&amp;lt;/math&amp;gt; с шагом по степеням двойки;&lt;br /&gt;
*	объём выборки &amp;lt;math&amp;gt;[10^3:10^7]&amp;lt;/math&amp;gt;  с шагом по степеням десятки;&lt;br /&gt;
&lt;br /&gt;
На следующем рисунке приведен график [[Глоссарий#Производительность|производительности]] выбранной реализации алгоритма Hard C - Means (HCM). &lt;br /&gt;
[[Файл:scheme1.png]]&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*  [https://github.com/artpar/Hard-Clustering-implementation Последовательная реализация на С++ ]&lt;br /&gt;
&lt;br /&gt;
*  [http://projects.jasmeet.me/2013/03/HardCMeans.html Последовательная реализация на MatLab ]&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Coctic</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:%D0%A8%D0%B8%D1%88%D0%BA%D0%BE%D0%B2_%D0%98%D0%BB%D1%8C%D1%8F_%D0%A1%D0%B5%D1%80%D0%B3%D0%B5%D0%B5%D0%B2%D0%B8%D1%87&amp;diff=20813</id>
		<title>Обсуждение участника:Шишков Илья Сергеевич</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:%D0%A8%D0%B8%D1%88%D0%BA%D0%BE%D0%B2_%D0%98%D0%BB%D1%8C%D1%8F_%D0%A1%D0%B5%D1%80%D0%B3%D0%B5%D0%B5%D0%B2%D0%B8%D1%87&amp;diff=20813"/>
		<updated>2016-12-13T14:42:11Z</updated>

		<summary type="html">&lt;p&gt;Coctic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Статья [[Алгоритм HCM (Hard C – Means)]] =&lt;br /&gt;
* Не указан вклад каждого автора [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:47, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:06, 1 ноября 2016 (MSK)&lt;br /&gt;
* п. 1.1 Стоит добавит ссылку на публикацию, в которой алгоритм был впервые описан (Jang, Sun and Mizutani) [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:47, 25 октября 2016 (MSK)&lt;br /&gt;
* Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:06, 1 ноября 2016 (MSK)&lt;br /&gt;
* п. 1.3 Сказано, что &amp;quot;На каждой итерации алгоритма происходит &amp;lt;math&amp;gt;CN&amp;lt;/math&amp;gt; таких вычислений&amp;quot;, однако определений C и N не приведено ни здесь, ни ранее. Ранее имеется определение для c (c малого), но это другой символ. [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:47, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:06, 1 ноября 2016 (MSK)&lt;br /&gt;
* Ссылки в списке литературы не содержат данных публикации, кроме названия и списка авторов. Веб-ссылки на какую-то версию публикации недостаточно. [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:52, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:06, 1 ноября 2016 (MSK)&lt;br /&gt;
** Замечания были приняты и исправлены огрехи. [[Участник:Темербекова_Гульгайша|Темербекова_Гульгайша]] ([[Обсуждение участника:Темербекова_Гульгайша|обсуждение]]) 23:40, 31 октября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
* Отсутствует п. 2.4. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 16:54, 16 ноября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 17:42, 13 декабря 2016 (MSK)&lt;br /&gt;
* Необходимо указать характеристики программно-аппаратной платформы (какой компилятор, с какими опциями использовался, какие версии библиотек, на каких узлах проводился запуск и т.д.). Указано, что запуск осуществлялся на Ломоносове, ссылка на MPI приведена на страницы, описывающие BlueGene/P, понять, какая реализация MPI использовалась, невозможно [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 17:42, 13 декабря 2016 (MSK)&lt;br /&gt;
* На неподписанном рисунке в п. 2.4. в подписи к оси аппликат указано, что по ней отложено время в секундах, в абзаце перед рисунком указано, что приведен график производительности. Что из этого верно, неясно. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 17:42, 13 декабря 2016 (MSK)&lt;/div&gt;</summary>
		<author><name>Coctic</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:Smirnov.maxim/BIRCH&amp;diff=20703</id>
		<title>Участник:Smirnov.maxim/BIRCH</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:Smirnov.maxim/BIRCH&amp;diff=20703"/>
		<updated>2016-12-12T09:57:13Z</updated>

		<summary type="html">&lt;p&gt;Coctic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Авторы: [[Участник:Светлана Морозова|Морозова Светлана]], [[Участник:Smirnov.maxim|Смирнов Максим]].&lt;br /&gt;
Вклад авторов:&lt;br /&gt;
&lt;br /&gt;
Смирнов Максим:&lt;br /&gt;
*п.1.5&lt;br /&gt;
*п.1.7&lt;br /&gt;
*п.1.8&lt;br /&gt;
*п.1.9&lt;br /&gt;
*п.2.7&lt;br /&gt;
&lt;br /&gt;
Морозова Светлана&lt;br /&gt;
*п.1.1&lt;br /&gt;
*п.1.2&lt;br /&gt;
*п.1.3&lt;br /&gt;
*п.1.4&lt;br /&gt;
*п.1.6&lt;br /&gt;
*п.1.10&lt;br /&gt;
*п.3&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Нахождение полезных для анализа закономерностей в больших объёмах данных с недавних пор вызывает значительный интерес. В связи с этим ввелось и стало активно развиваться такое понятие как &#039;&#039;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7 кластеризация]&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Ранние работы и алгоритмы, разработанные в этой области, не уделяли достаточного внимания анализу очень больших наборов данных или минимизации издержек на процессы ввода-вывода.&lt;br /&gt;
Решением этих проблем стал алгоритм, известный как BIRCH.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIRCH&#039;&#039;&#039;&amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации // Интеллектуальные технологии и системы. Сборник учебно-методических работ и статей аспирантов и студентов. – М.: НОК «CLAIM», 2006. – Выпуск 8. – С. 130-142.&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;T Zhang, R Ramakrishnan, M Livny. BIRCH: An Efficient Data Clustering Method for Very Large Databases - 1996. - С.103-114)&amp;lt;/ref&amp;gt; - алгоритм, применяемый в области [https://ru.wikipedia.org/wiki/Data_mining Data mining] и использующий принципы [https://ru.wikipedia.org/wiki/%D0%98%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F иерархической кластеризации].&lt;br /&gt;
&lt;br /&gt;
Если имеется очень большой набор данных, то в пространстве он распределен, как правило, неравномерно. Кластерный анализ определяет места наибольшего и наименьшего скоплений, чтобы таким образом понять всю картину целиком. Кроме того, полученные кластеры визуализируются гораздо нагляднее, чем начальные &amp;quot;сырые&amp;quot; данные.&lt;br /&gt;
Задачей алгоритмов кластеризации является не только простое разбиение данных на кластеры, но и работа в рамках ограниченного объёма доступной памяти (как правило, её объём гораздо меньше, чем размер исходного набора данных) и минимизация времени, требуемого на операции ввода-вывода.&lt;br /&gt;
&lt;br /&gt;
Для наилучшего решения этих проблем BIRCH распределяет входящие данные по кластерам динамически. Для эффективной кластеризации алгоритму требуется всего одно сканирование данных (т.е. с увеличением количества данных сложность увеличивается линейно). А при помощи одной (или более) дополнительных итераций можно и далее улучшать эффективность. BIRCH также является первым алгоритмом, предложенным для эффективного управления &amp;quot;шумами&amp;quot; (данными, которые не вписываются в общее представление модели).&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Теоретическая основа ===&lt;br /&gt;
&lt;br /&gt;
Пусть в кластере имеются &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}, i=1,2,...,N&amp;lt;/math&amp;gt;.&lt;br /&gt;
Тогда &#039;&#039;&#039;центроид&#039;&#039;&#039; &amp;lt;math&amp;gt;{\vec{{X_0}}}&amp;lt;/math&amp;gt;, &#039;&#039;&#039;радиус&#039;&#039;&#039; &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &#039;&#039;&#039;диаметр&#039;&#039;&#039; &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластера определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;{\vec{X_0}}=\frac{\sum_{i=1}^N\vec{X_i}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{\sum_{i=1}^N{(\vec{X_i} - \vec{X_0})}^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{\sum_{i=1}^N\sum_{j=1}^N{(\vec{X_i} - \vec{X_j})}^2}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; - это среднее расстояние от каждой точки до центроида. &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; - это среднее расстояние между парами в кластере. Данные величины являются альтернативными метриками плотности кластера относительно центроида.&lt;br /&gt;
&lt;br /&gt;
Для измерения близости друг к другу двух кластеров вводятся следующие метрики:&lt;br /&gt;
&lt;br /&gt;
пусть даны центроиды двух кластеров &amp;lt;math&amp;gt;\vec{X_{01}}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\vec{X_{02}}&amp;lt;/math&amp;gt;.&lt;br /&gt;
Евклидова метрика &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt; и метрика Манхэттена &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt; между двумя кластерами определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_0 = ((\vec{X_{01}}-\vec{X_{02}})^2)^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_1 = |\vec{X_{01}}-\vec{X_{02}}| = \sum_{i=1}^d |{\vec{X_{01}}}^{(i)}-{\vec{X_{02}}}^{(i)}| &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть имеются два кластера, содержащих соответственно  &amp;lt;math&amp;gt;N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;N_2&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i= 1,2, ...,N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\{\vec{X_j}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j= N_1+1,N_1+2, ...,N_1+N_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Среднее расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &#039;&#039;&#039;среднее внутрикластерное расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &#039;&#039;&#039;дисперсия&#039;&#039;&#039; &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; для двух кластеров определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{\sum_{i=1}^{N_1}\sum_{j=N_1+1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{N_1N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{\sum_{i=1}^{N_1+N_2}\sum_{j=1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_4 = \sum_{k=1}^{N_1+N_2}(\vec{X_k} - \frac{\sum_{i=1}^{N_1+N_2}\vec{X_i}}{N_1+N_2})^2 - \sum_{i=1}^{N_1}(\vec{X_i} - \frac{\sum_{i=1}^{N_1}\vec{X_i}}{N_1})^2 - \sum_{j=N_1+1}^{N_1+N_2}(\vec{X_j} - \frac{\sum_{i=N_1+1}^{N_1+N_2}\vec{X_i}}{N_2})^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Таким образом, величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; относятся к отдельным кластерам, а &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; - к объединению двух кластеров.&lt;br /&gt;
&lt;br /&gt;
=== Кластерный элемент и кластерное дерево ===&lt;br /&gt;
&lt;br /&gt;
В основе концепции алгоритма BIRCH лежат понятия &#039;&#039;&#039;кластерного элемента&#039;&#039;&#039; и &#039;&#039;&#039;кластерного дерева (CF Tree)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====Кластерный элемент ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; Пусть в кластере содержатся  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности  &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;:&amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;i=1,2,...,N&amp;lt;/math&amp;gt;. &lt;br /&gt;
&#039;&#039;&#039;Кластерный элемент (CF)&#039;&#039;&#039; - тройка чисел, характеризующая информацию о кластере: &lt;br /&gt;
&amp;lt;math&amp;gt;CF = (N, \vec{LS}, SS)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - количество элементов входных данных, содержащихся в кластере, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; - линейная сумма входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}\vec{X_i}&amp;lt;/math&amp;gt;), &amp;lt;math&amp;gt;SS&amp;lt;/math&amp;gt; - сумма квадратов входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}{\vec{X_i}}^2&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Теорема&#039;&#039;&#039; Пусть &amp;lt;math&amp;gt;CF_1 = (N_1, \vec{LS_1}, SS_1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;CF_2 = (N_1, \vec{LS_2}, SS_2)&amp;lt;/math&amp;gt; - CF векторы двух непересекающихся кластеров. Тогда при их объединении образуется кластер со следующим CF вектором: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF = CF_1 + CF_2 = (N_1+N_2, \vec{LS_1}+\vec{LS_2}, SS_1+SS_2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Из указанных выше определения и теоремы вытекает тот факт, что при объединении кластеров их CF вектор может вычисляться инкрементно и точно. &lt;br /&gt;
Легко показать, что вычислить величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;, как и обычные метрики, также не составит труда.&lt;br /&gt;
&lt;br /&gt;
Таким образом, в данном случае информацией о кластере является не весь набор точек, а вектор CF. Хранение одного только вектора может показаться неэффективным, но этого вполне достаточно для оперирования всеми необходимыми метриками, на основе которых принимаются решения в алгоритме BIRCH.&lt;br /&gt;
&lt;br /&gt;
==== Кластерное дерево ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; &#039;&#039;&#039;Кластерное дерево (CF Tree)&#039;&#039;&#039; - это взвешенно сбалансированное дерево с двумя параметрами: &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - коэффициент разветвления, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - пороговая величина.&lt;br /&gt;
&lt;br /&gt;
Каждый нелистьевой узел дерева имеет не более чем &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; вхождений узлов следующей формы: &amp;lt;math&amp;gt;[CF_i,child_i]&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i=1,2,...,B&amp;lt;/math&amp;gt;, &#039;&#039;child&#039;&#039; - указатель на i-й дочерний узел, &amp;lt;math&amp;gt;CF_i&amp;lt;/math&amp;gt; - CF вектор соответствующего подкластера.&lt;br /&gt;
&lt;br /&gt;
Каждый листьевой узел имеет ссылку на два соседних узла (&#039;&#039;prev&#039;&#039; и &#039;&#039;next&#039;&#039;) для того, чтобы связать все узлы для эффективного сканирования.&lt;br /&gt;
Все листьевые узлы должны удовлетворять пороговому ограничению &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, т.е. диаметр (радиус) не должен превосходить &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;.&lt;br /&gt;
В процессе вставки новых данных CF дерево строится динамически. Оно использует вставку данных для кластеризации точно также как &amp;lt;math&amp;gt;B+&amp;lt;/math&amp;gt; [https://ru.wikipedia.org/wiki/B%2B-%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE дерево] использует её для поиска.&lt;br /&gt;
CF дерево очень компактно, поскольку каждый листьевой узел - это не просто точка, а подкластер (который объединяет множество точек с учётом ограничения &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Операция вставки в &#039;&#039;&#039;CF&#039;&#039;&#039; дерево ====&lt;br /&gt;
&lt;br /&gt;
Опишем алгоритм вставки элемнта &amp;lt;math&amp;gt;Ent&amp;lt;/math&amp;gt; в CF дерево:&lt;br /&gt;
&lt;br /&gt;
1) &#039;&#039;Определение подходящего листа&#039;&#039;: Начиная с корня, алгоритм рекурсивно спускается по CF дереву, выбирая &#039;&#039;&#039;ближайший&#039;&#039;&#039; дочерний узел в соответствии с выбранной метрикой &amp;lt;math&amp;gt;D0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D4&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &#039;&#039;Преобразование листа&#039;&#039;: Когда алгоритм доходит до листа, он находит ближайшую листьевой элемент, скажем, &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;, а затем проверяет, можно ли добавить &#039;&#039;Ent&#039;&#039; к &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt; без нарушения порогового условия. Если да, то с учётом этого изменяется CF вектор для &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;; если нет, то &#039;&#039;Ent&#039;&#039; становится новым элементом листа. Если в листе для этого достаточно места, то шаг окончен, иначе он должен &amp;quot;расщепиться&amp;quot;. Расщепление узла производится при помощи выбора за основу наиболее удалённой друг от друга пары элементов и перераспределение оставшихся элементов в соответствии с выбранным критерием близости.&lt;br /&gt;
&lt;br /&gt;
3) &#039;&#039;Преобразование пути к листу&#039;&#039;: После вставки &#039;&#039;Ent&#039;&#039; в лист мы должны обновить информацию о CF для каждого нелистьевого элемента на пути к листу. При отсутствии расщепления это означает простое сложение CF векторов для отражения факта добавления &#039;&#039;Ent&#039;&#039;. Расщепление листа же требует вставки нового нелистьевого элемента в родительский узел для задания только что созданного листа. Если у родителя есть место для этого элемента, то необходимо просто преобразовать CF векторы на всех более высоких уровнях. В общем случае, однако, нам также придётся расщепить родительский узел, и так далее до корня. Если расщеплён корень, то высота дерева увеличивается на единицу.&lt;br /&gt;
&lt;br /&gt;
4) &#039;&#039;Улучшение слияния&#039;&#039;: Расщепление вызвано ограничением на размер узла, который не зависит от кластеризационных свойств данных. Если во входящем потоке присутствуют &amp;quot;искажённые&amp;quot; (из областей с низкой плотностью) данные, это может повлиять на качество кластеризации, а также уменьшить эффективность использования памяти. Дополнительный шаг алгоритма помогает решить эти проблемы: предположим, что произошло расщепление листа, и распространение этого процесса остановилось на некотором нелистьевом узле &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt;, то есть &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; может вместить дополнительный элемент, полученный после расщепления. Теперь мы сканируем узел &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; для нахождения двух наиболее близких элементов. Если это не пара, отвечающая расщеплению, мы пытаемся объединить их и поставить в соответствие два дочерних узла. Если количество элементов в дочерних узлах  больше B, мы снова расщепляем результат объединения.&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;R&amp;lt;/math&amp;gt; или диаметра &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластерного элемента. Выполняется при попытке вставить новый элемент в один из подкластеров листьевого узла дерева.&lt;br /&gt;
&lt;br /&gt;
* расстояния между двумя элементами. Выполняется при поиске ближайшего по отношению к новому элементу подкластера в узле дерева по одной из рассмотренных в разд. 1.2.1 метрик &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Зная характеристики кластерных элементов &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;, в результате алгебраических преобразований можно получить следующие упрощенные формулы вычисления необходимых значений:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\vec{X_0} = \frac{\vec{LS}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{SS - 2\vec{X_0}\vec{LS} + N(\vec{X_0})^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{2(N \cdot SS - (\vec{LS})^2)}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{N_1 \cdot SS_2 + N_2 \cdot SS_1 - 2\vec{LS_1}\vec{LS_2}}{N_1 \cdot N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{2((N_1+N_2)(SS_1+SS_2)-(\vec{LS_1}+\vec{LS_2})^2)}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Реализация алгоритма BIRCH состояит из следующих четырёх фаз:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 1&#039;&#039;&#039;. Главной задачей фазы 1 является сканирование всех данных и построение в памяти исходного CF дерева, используя заданное количество памяти. Это дерево стремится отразить информацию о кластеризации данных настолько хорошо, насколько это позволяют ограничения по памяти. При этом плотно распределённые данные группируются в подкластеры, а более разрозненные данные удаляются. После завершения фазы 1 вспомогательные вычисления в дальнейших фазах будут:&lt;br /&gt;
&lt;br /&gt;
1) быстрее, потому что (а) больше не нужны операции ввода-вывода, (b) проблема кластеризации начальных данных упрощается до проблемы кластеризации подкластеров в листьях;&lt;br /&gt;
&lt;br /&gt;
2) точнее, потому что (а) большинство данных с низкой плотностью удалены, (b) оставшиеся данные распределены оптимально (в соответствии с доступным количеством памяти);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 2&#039;&#039;&#039;. Данная фаза является опциональной. Известно, что существующие методы глобальной кластеризации, используемые в рамках фазы 3, имеют различные диапазоны входных значений, при которых их реализация наиболее эффективна. Поэтому потенциально существует пробел между размером фазы 1 и входными значениями фазы 3. И фаза 2 как раз является недостающим связующим звеном: так же как и фаза 1, она сканирует листьевые элементы начального CF дерева для того, чтобы построить меньшее дерево, удаляя ещё больше элементов с низкой плотностью и группируя переполненные подкластеры в большие кластеры.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 3&#039;&#039;&#039;. В данной фазе для листьевых элементов применяется (любой подходящий) алгоритм глобальной кластеризации. Существующие алгоритмы кластеризации наборов точек могут также работать с наборами подкластеров, каждый из которых представлен своим CF вектором. Зная CF вектор, можно вычислить центроид и в дальнейшем заменить всю информацию о кластере этим значением (этого достаточно для вычисления большинства необходимых метрик). После фазы 3 мы получаем набор кластеров, который отражает основные характеристики распределяемых данных.&lt;br /&gt;
Однако, всё ещё могут оставаться некоторые неточности, для устранения которых существует фаза 4.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 4&#039;&#039;&#039;. Данная фаза является опциональной и влечёт за собой затраты на дополнительное сканирование данных для корректировки неточностей и дальнейшего улучшения кластеризации. Фаза 4 использует центроиды кластеров, полученные в фазе 3 для как основы и перераспределяет точки входных данных в ближайшие для них основы для получения нового списка кластеров. Фаза 4, если это необходимо пользователю, может быть расширена дополнительными проходами для уверенности в том, что результат приближается к оптимальному.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Последовательную реализацию основных операций алгоритма BIRCH можно продемонстрировать на примере следующего фрагмента кода на языке C++:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot;&amp;gt;&lt;br /&gt;
void CF_Node::insert(const CF_Cluster &amp;amp;entry)&lt;br /&gt;
{&lt;br /&gt;
    //Находим ближайший к новому элементу подкластер в узле&lt;br /&gt;
    СF_Vector_it closest = entry.findClosest(subclusters);&lt;br /&gt;
    //Если узел пустой, добавляем в него новый подкластер&lt;br /&gt;
    if (closest == subclusters.end()) {&lt;br /&gt;
        subclusters.push_back(entry);&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    closest-&amp;gt;add(entry);&lt;br /&gt;
    //Если узел является листьевым, и ближайший подкластер не может вместить&lt;br /&gt;
    //новый элемент, добавляем в узел новый подкластер&lt;br /&gt;
    if (leaf) {&lt;br /&gt;
        if (closest-&amp;gt;D &amp;gt; threshold) {&lt;br /&gt;
            closest-&amp;gt;remove(entry);&lt;br /&gt;
            subclusters.push_back(entry);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else {&lt;br /&gt;
        CF_Node *node = closest-&amp;gt;child;&lt;br /&gt;
        node-&amp;gt;insert(entry);&lt;br /&gt;
        //Если при добавлении нового элемента в дочерний узел тот переполнился,&lt;br /&gt;
        //расщепляем его        &lt;br /&gt;
        if (node-&amp;gt;getSubclusters().size() &amp;gt; bFactor) {&lt;br /&gt;
            CF_Vector newClusters = node-&amp;gt;splitNode();&lt;br /&gt;
            delete node;&lt;br /&gt;
            subclusters.erase(closest);&lt;br /&gt;
            subclusters.insert(subclusters.end(), newClusters.begin(), newClusters.end());&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    //Если узел является корневым и он переполнен, расщепляем его&lt;br /&gt;
    if (root &amp;amp;&amp;amp; subclusters.size() &amp;gt; bFactor) {&lt;br /&gt;
        subclusters = splitNode();&lt;br /&gt;
        leaf = false;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
CF_Vector CF_Node::splitNode()&lt;br /&gt;
{&lt;br /&gt;
    if (subclusters.size() &amp;lt; 2)&lt;br /&gt;
        return (root) ? subclusters : CF_Vector{CF_Cluster(this)};&lt;br /&gt;
    //Находим пару наиболее удаленных друг от друга подкластеров&lt;br /&gt;
    CF_Vector_it pole1, pole2;&lt;br /&gt;
    data_t longestDist = 0.0;&lt;br /&gt;
    for (auto lhs = subclusters.begin(); lhs != subclusters.end() - 1; ++lhs) {&lt;br /&gt;
        for (auto rhs = lhs + 1; rhs != subclusters.end(); ++rhs) {&lt;br /&gt;
            auto distance = getDistance(*lhs, *rhs);&lt;br /&gt;
            if (distance &amp;gt; longestDist) {&lt;br /&gt;
                longestDist = distance;&lt;br /&gt;
                pole1 = lhs;&lt;br /&gt;
                pole2 = rhs;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    //Разделяем множество всех подкластеров узла на две части&lt;br /&gt;
    CF_Vector subclusters1, subclusters2;&lt;br /&gt;
    for (auto it = subclusters.begin(); it != subclusters.end(); ++it) {&lt;br /&gt;
        if (getDistance(*it, *pole1) &amp;lt; getDistance(*it, *pole2))&lt;br /&gt;
            subclusters1.push_back(*it);&lt;br /&gt;
        else&lt;br /&gt;
            subclusters2.push_back(*it);&lt;br /&gt;
    }&lt;br /&gt;
    //Создаем два новых узла&lt;br /&gt;
    CF_Node *node1 = new CF_Node(threshold, bFactor, count, leaf, subclusters1),&lt;br /&gt;
            *node2 = new CF_Node(threshold, bFactor, count, leaf, subclusters2);&lt;br /&gt;
    //Связываем листья&lt;br /&gt;
    if (leaf) {&lt;br /&gt;
        if (prevLeaf) {&lt;br /&gt;
            node1-&amp;gt;setPrevLeaf(prevLeaf);&lt;br /&gt;
            prevLeaf-&amp;gt;setNextLeaf(node1);&lt;br /&gt;
        }&lt;br /&gt;
        if (nextLeaf) {&lt;br /&gt;
            node2-&amp;gt;setNextLeaf(nextLeaf);&lt;br /&gt;
            nextLeaf-&amp;gt;setPrevLeaf(node2);&lt;br /&gt;
        }&lt;br /&gt;
        node1-&amp;gt;setNextLeaf(node2);&lt;br /&gt;
        node2-&amp;gt;setPrevLeaf(node1);&lt;br /&gt;
    }&lt;br /&gt;
    CF_Cluster cluster1(node1), cluster2(node2);&lt;br /&gt;
    return CF_Vector{cluster1, cluster2};&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Для начала проанализируем вычислительную сложность фазы 1.&lt;br /&gt;
Максимальный размер дерева &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt; - ограничение по памяти на размер узла, а &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - общий объем памяти. Для того чтобы вставить элемент, мы должны пройти путь от корня до листа (это около &amp;lt;math&amp;gt;1+log_B\frac{M}{P}&amp;lt;/math&amp;gt; узлов). В каждом узле в поисках &amp;quot;ближайшего&amp;quot; нам необходимо просмотреть B элементов; сложность для каждого элемента пропорциональна размерности &#039;&#039;d&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Поэтому сложность вставки всех входных точек &amp;lt;math&amp;gt;O(d \cdot N \cdot B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В случае, когда необходимо перестроить дерево, предположим, что ES - это размер CF элемента. Существует максимум &amp;lt;math&amp;gt;\frac{M}{ES}&amp;lt;/math&amp;gt; листьевых элементов для вставки, поэтому сложность повторной вставки листьевых элементов &amp;lt;math&amp;gt;O(d \cdot \frac{M}{ES} \cdot B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Количество итераций перестройки дерева зависит от пороговой величины. На самом деле, это около &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; (двоичное основание появилось из-за того, что мы не можем провести оценку более чем в 2 раза отличающуюся от текущего размера). &amp;lt;math&amp;gt;N_0&amp;lt;/math&amp;gt; - это число входных точек, загруженных в память с пороговым ограничением &amp;lt;math&amp;gt;T_0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Соответственно, итоговая сложность фазы 1 &amp;lt;math&amp;gt;O(d \cdot N \cdot B(1+log_B\frac{M}{P})+log_2\frac{N}{N_0} \cdot d \cdot \frac{M}{ES} \cdot B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Анализ фазы 2 проводится аналогично.&lt;br /&gt;
&lt;br /&gt;
Что касается операций ввода-вывода, то в фазе 1 данные сканируются один раз, а в фазе 2 не сканируются вовсе.&lt;br /&gt;
Некоторое количество вычислений связано с удалением точек из областей с низкой плотностью.&lt;br /&gt;
Если количество доступной для этой операции памяти не больше &#039;&#039;M&#039;&#039; и проведено порядка &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; перестроек дерева, то сложность ввода-вывода для фазы 1 существенно не отличается от сложности чтения из файла. Основываясь рассуждениях выше, сложность фаз 1 и 2 будет линейно увеличиваться с ростом N.&lt;br /&gt;
&lt;br /&gt;
В фазе 3 нет операций ввода-вывода. Её сложность ограничена константой, которая зависит от максимального размера входных данных, и варианта выбранного алгоритма для кластеризации. &lt;br /&gt;
&lt;br /&gt;
Фаза 4 снова сканирует данные и записывает каждую точку в подходящий кластер; время работы пропорционально &amp;lt;math&amp;gt;N \cdot K&amp;lt;/math&amp;gt;.   &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&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;D_2=\frac{N_1\cdot SS_2+N_2\cdot SS_1-2 \cdot \vec{LS_1}\cdot \vec{LS_2}}{N_1\cdot N_2}&amp;lt;/math&amp;gt;, где&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF_1=[N_1,\vec{LS_1},SS_1]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF_2=[N_2,\vec{LS_2},SS_2]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:ZgYL51QJsQk.jpg|600px|thumb|center]]&lt;br /&gt;
&lt;br /&gt;
=== Поиск ближайшего подкластера ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;E&amp;lt;/math&amp;gt; - новый элемент&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF_i, i = 1,...,B&amp;lt;/math&amp;gt; - подкластеры узла&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - операция min&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\rho&amp;lt;/math&amp;gt; - нахождение расстояния&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:PFA16KHUQ3I.jpg|600px|thumb|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Скалярное произведение ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;s = \vec{x}\cdot\vec{y}=\sum_{i=1}^d x_i\cdot y_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Xb7FYXVMPpQ.jpg|600px|thumb|center]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&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;\vec{LS},\vec{X0}, R, D, D_0-D_4&amp;lt;/math&amp;gt;, в процессе чего выполняются операции сложения и скалярного произведения векторов.&lt;br /&gt;
&lt;br /&gt;
Таким образом, параллельная сложность фазы 1 алгоритма будет равна &amp;lt;math&amp;gt;O((N + log_2\frac{N}{N_0} \cdot \frac{M}{ES})(log_2 B + log_2 d)(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Другим способом параллелизации алгоритма может служить создание и заполнение сразу множества кластерных деревьев, между которыми будут распределены входные данные. Множество всех подкластеров листьевых узлов полученных таким образом деревьев может быть подвергнуто глобальной кластеризации с помощью какого-либо из известных параллельных алгоритмов, например, k-средних&amp;lt;ref&amp;gt;[A Garg, N Gupta PBIRCH: A Scalable Parallel Clustering algorithm for Incremental Data //10th International Database Engineering and Applications Symposium (IDEAS&#039;06), 2006&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; набор из &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек &amp;lt;math&amp;gt;\{X_i\}, i=1,...,N&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем входных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;N \cdot d&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; кластерное дерево с не более чем &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt; узлами.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительная мощность алгоритма имеет порядок &amp;lt;math&amp;gt;O(\frac{d \cdot B \cdot (1+log_B\frac{M}{P}) \cdot (N +log_2\frac{N}{N_0} \cdot \frac{M}{ES})}{N \cdot d + M})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм BIRCH не является детерминированным, так как процесс его выполнения во многом зависит от входных данных.&lt;br /&gt;
&lt;br /&gt;
К достоинствам алгоритма можно отнести следующие его свойства:&lt;br /&gt;
&lt;br /&gt;
1. BIRCH является локальным алгоритмом, то есть каждое решение о каждом элементе кластера принимается без повторного сканирования данных или уже существующих кластеров. Используются только метрики, отражающие близость элементов друг к другу.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH использует факт неравномерного распределения данных в пространстве и поэтому не все данные рассматриваются как одинаково важные для построения кластера. Области с большой плотностью обрабатываются как единый кластер. Данные в более разреженных областях могут удаляться (опционально).&lt;br /&gt;
&lt;br /&gt;
3. BIRCH использует всю доступную память для получения наилучших из возможных подкластеров, в то же время минимизируя затраты на операции ввода/вывода. Оптимизация процесса кластеризации достигается за счет использования взвешенно-сбалансированного дерева. При этом время исполнения линейно.&lt;br /&gt;
&lt;br /&gt;
4. BIRCH не требует всего набора данных заранее (при этом просматривает его всего один раз).&lt;br /&gt;
&lt;br /&gt;
В свою очередь, недостатки алгоритма можно сформулировать следующим образом:&lt;br /&gt;
&lt;br /&gt;
1. Алгоритм позволяет работать только с числовыми данными.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH хорошо выделяет только кластеры сферической формы.&lt;br /&gt;
&lt;br /&gt;
3. Существует необходимость в задании пороговых значений.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
Проведём исследование масштабируемости параллельной реализации алгоритма BIRCH. Исследование проводилось на суперкомпьютере &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;
[[file:Масштабируемость параллельной реализации алгоритма BIRCH. Производительность.png|thumb|center|700px|Рисунок 1. График времени работы параллельной реализации алгоритма BIRCH. ]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[file:Масштабируемость параллельной реализации алгоритма BIRCH. Эффективность.png|thumb|center|700px|Рисунок 2. График эффективности распараллеливания алгоритма BIRCH относительно последовательной реализации. ]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Набор изменяемых параметров запуска реализации алгоритма и границы значений параметров алгоритма: &lt;br /&gt;
*	число процессоров [8 : 80] с шагом 8&lt;br /&gt;
*	число точек [100 000 : 1 000 000] с шагом 100 000&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В результате проведённых экспериментов был получен следующий диапазон эффективности реализации алгоритма:&lt;br /&gt;
*	минимальная эффективность реализации 9,13% (80 процессоров, 100 000 точек)&lt;br /&gt;
*	максимальная эффективность реализации 235,42% (8 процессоров, 800 000 точек)&lt;br /&gt;
&lt;br /&gt;
Полученные результаты могут быть объяснены недерминированностью алгоритма BIRCH и существенной зависимостью времени его работы от входных данных.&lt;br /&gt;
&lt;br /&gt;
Оценка масштабируемости параллельной реализации:&lt;br /&gt;
*	По числу процессов:  при увеличении числа процессов эффективность распараллеливания снижается. При количестве процессов &amp;lt;math&amp;gt;n&amp;gt;30&amp;lt;/math&amp;gt; темп снижения становится несущественным.&lt;br /&gt;
* По размеру задачи: при увеличении размера входных данных эффективность растет неравномерно, что свидетельствует о сложной зависимости от входных данных.&lt;br /&gt;
&lt;br /&gt;
Для исследования возможностей паралеллизма алгоритма BIRCH была написана [https://github.com/duran-duran/birch реализация на языке C++] с использованием технологии MPI. В данной реализации входные данные равномерно распределяются между всеми процессами, в каждом из которых выполняется построение собственного кластерного дерева. Листьевые элементы полученных деревьев затем подвергаются глобальной кластеризации с помощью распределенного алгоритма k-средних. В качестве входных данных использовались точки размерности &amp;lt;math&amp;gt;d=5&amp;lt;/math&amp;gt;, координаты которых были равномерно распределены в диапазоне &amp;lt;math&amp;gt;[-10000;10000]&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;
* [http://scikit-learn.org/stable/modules/generated/sklearn.cluster.Birch.html scikit-learn]&lt;br /&gt;
* [http://cucis.ece.northwestern.edu/projects/DMS/MineBench.html NU-MineBench]&lt;br /&gt;
Пользовательские реализации:&lt;br /&gt;
* [https://code.google.com/archive/p/jbirch/ JBIRCH]&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Coctic</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9C%D0%BE%D1%80%D0%BE%D0%B7%D0%BE%D0%B2%D0%B0&amp;diff=20702</id>
		<title>Обсуждение участника:Светлана Морозова</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9C%D0%BE%D1%80%D0%BE%D0%B7%D0%BE%D0%B2%D0%B0&amp;diff=20702"/>
		<updated>2016-12-12T09:57:03Z</updated>

		<summary type="html">&lt;p&gt;Coctic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Статья [[Участник:Smirnov.maxim/BIRCH]] ==&lt;br /&gt;
&lt;br /&gt;
=== Неправильная структура статьи ===&lt;br /&gt;
* Слово &amp;quot;Часть&amp;quot; в заголовках лишнее [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 17:55, 21 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:01, 31 октября 2016 (MSK)&lt;br /&gt;
* Название пункта 1.3 не из шаблона [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 17:55, 21 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:01, 31 октября 2016 (MSK)&lt;br /&gt;
* Пункты 1.4-1.5 должны быть 1.3-1.4 [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 17:55, 21 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:01, 31 октября 2016 (MSK)&lt;br /&gt;
* Пункты 3.1 шаблоном не предусмотрен [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 17:55, 21 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:01, 31 октября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
=== Отсутствующие части ===&lt;br /&gt;
* Отсутствует указание автора [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 17:55, 21 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:01, 31 октября 2016 (MSK)&lt;br /&gt;
* Нет пунктов 1.5-1.10, 2.7  [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 17:55, 21 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:01, 31 октября 2016 (MSK)&lt;br /&gt;
* В тексте есть ссылки на 2 рисунка, которых нет [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 17:55, 21 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:01, 31 октября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
=== Замечания по тексту ===&lt;br /&gt;
* Пункт 1.3: есть указание на &amp;quot;фазу 1&amp;quot;, нет описания  дальнейших фаз [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 17:55, 21 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:01, 31 октября 2016 (MSK)&lt;br /&gt;
* Пункт 1.3: названия подпунктов &amp;quot;фаза 1&amp;quot;, &amp;quot;уменьшаемость&amp;quot;, &amp;quot;пороговые значения&amp;quot;, &amp;quot;достоинства алгоритма&amp;quot; не выглядят логическими частями описания алгоритма [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 17:55, 21 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:01, 31 октября 2016 (MSK)&lt;br /&gt;
* В разделе &amp;quot;Литература&amp;quot; единственная ссылка на Википедию, причем на на конкретную страницу, а на Википедию вообще (причем ссылка не ведет никуда, это просто текст). Фактически список литературы отсутствует. [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 17:55, 21 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:01, 31 октября 2016 (MSK)&lt;br /&gt;
--------------------------&lt;br /&gt;
* в списке авторов не указан вклад каждого автора [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:01, 31 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:51, 7 ноября 2016 (MSK)&lt;br /&gt;
* п. 1.8 не приведена оценка параллельной сложности алгоритма [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:01, 31 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:51, 7 ноября 2016 (MSK)&lt;br /&gt;
* п. 1.9 не приведены оценки объема входных и выходных данных [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:01, 31 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:51, 7 ноября 2016 (MSK)&lt;br /&gt;
* п. 1.10 не приведена оценка вычислительной мощности алгоритма [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:01, 31 октября 2016 (MSK)&lt;br /&gt;
** Не исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:51, 7 ноября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 16:51, 16 ноября 2016 (MSK)&lt;br /&gt;
* в списке литературы у ссылок отсутствуют выходные данные, позволяющие их однозначно идентифицировать [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:01, 31 октября 2016 (MSK)&lt;br /&gt;
** Исправлено частично. Ссылка 1 по-прежнему не имеет достаточного количества выходных данных [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:51, 7 ноября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 16:51, 16 ноября 2016 (MSK)&lt;br /&gt;
* Отсутствует п. 2.4. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 16:51, 16 ноября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:57, 12 декабря 2016 (MSK)&lt;br /&gt;
* Необходимо указать характеристики программно-аппаратной платформы (какой компилятор, с какими опциями использовался, какие версии библиотек, на каких узлах проводился запуск и т.д.) [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:57, 12 декабря 2016 (MSK)&lt;/div&gt;</summary>
		<author><name>Coctic</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Demon_smd&amp;diff=20036</id>
		<title>Обсуждение участника:Demon smd</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Demon_smd&amp;diff=20036"/>
		<updated>2016-12-05T07:31:34Z</updated>

		<summary type="html">&lt;p&gt;Coctic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Статья [[Нечеткий алгоритм С средних]] =&lt;br /&gt;
* не указан вклад каждого автора [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:58, 25 октября 2016 (MSK) - исправлено&lt;br /&gt;
:: Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:29, 31 октября 2016 (MSK)&lt;br /&gt;
* п. 1.9 не приведены оценки объема входных и выходных данных [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:58, 25 октября 2016 (MSK) - исправлено&lt;br /&gt;
:: Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:29, 31 октября 2016 (MSK)&lt;br /&gt;
* п. 2.4. Не приведена ссылка на текст исследуемой программы [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 18:28, 16 ноября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:32, 28 ноября 2016 (MSK)&lt;br /&gt;
* п. 2.4. Не указана аппаратная платформа, на которой проводилось тестирование [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 18:28, 16 ноября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:32, 28 ноября 2016 (MSK)&lt;br /&gt;
* п. 2.4. На рис. 2 и 3 подпись вертикальной оси накладывается на подписи шкалы  [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 18:28, 16 ноября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:32, 28 ноября 2016 (MSK)&lt;br /&gt;
* п. 2.4. Не приведено никаких сведений о масштабируемости исследуемой программы. На рис. 2 и 3 приведены графики зависимости некоей &amp;quot;сложности&amp;quot; (какя сложность имеется в виду - не указано) от разных параметров. Как из этих графиков извлечь сведения о масштабируемости - не указано. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 18:28, 16 ноября 2016 (MSK)&lt;br /&gt;
** Исправлено частично. В осях стало время в секундах, в подписях к рисункам по-прежнему непонятная &amp;quot;сложность&amp;quot;. Что в итоге на рисунках - неясно. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:32, 28 ноября 2016 (MSK)&lt;br /&gt;
*** Указали в подписях к рисункам &amp;quot;зависимость времени работы&amp;quot;&lt;br /&gt;
**** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:31, 5 декабря 2016 (MSK)&lt;br /&gt;
* Графики на рис. 2 и 3 плохо читаются [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:32, 28 ноября 2016 (MSK)&lt;br /&gt;
** Добавили цветные поверхности&lt;br /&gt;
*** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:31, 5 декабря 2016 (MSK)&lt;br /&gt;
* Необходимо указать характеристики программно-аппаратной платформы (какой компилятор, с какими опциями использовался, какие версии библиотек, на каких узлах проводился запуск и т.д.) [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:32, 28 ноября 2016 (MSK)&lt;br /&gt;
**Указали компилятор и характеристики узлов на IBM Blue Gene/P&lt;br /&gt;
*** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:31, 5 декабря 2016 (MSK)&lt;/div&gt;</summary>
		<author><name>Coctic</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:Demon_smd/%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=20035</id>
		<title>Участник:Demon smd/Нечеткий алгоритм С средних</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:Demon_smd/%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=20035"/>
		<updated>2016-12-05T07:31:04Z</updated>

		<summary type="html">&lt;p&gt;Coctic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|{{REVISIONUSER}}}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних (Fuzzy C-means)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(C^2*N*D*IterNumber)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(\log_{2}C^4*|X|^3) * IterNumber&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(C^2*|X|)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;|X|*p&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; - размерность входных векторов&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;|X|*C &amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы описания алгоритма: &lt;br /&gt;
[[Участник:Demon smd|Д.А.Гуськов]] &lt;br /&gt;
[[Участник:marina abramenkova|М.А.Абраменкова]]&lt;br /&gt;
Во все разделы вклад равноценный.&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
Нечёткий алгоритм кластеризации С-средних был разработан (для случая m=2) J.C. Dunn в 1973 г. &lt;br /&gt;
&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; &lt;br /&gt;
и усовершенствован (для случая m&amp;gt;1) &lt;br /&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;
. В отличие от алгоритма c-means данный метод кластеризации предполагает, что входные данные могут принадлежать более, чем одному кластеру одновременно.&lt;br /&gt;
Алгоритм получает на вход набор кластеризуемых векторов, количество кластеров, коэффициент неопределённости m и коэффициент &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;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;
=== Математическое описание алгоритма ===&lt;br /&gt;
Нечеткий алгоритм С средних минимизирует величину:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
J_{m} = \sum_{i = 1}^{N}\sum_{j = 1}^{C}u_{i,j}^m\left\Vert{x_{i}-c_{j}}\right\|^2 &amp;amp; , &amp;amp; &amp;amp;  1 \le m \le \infty , \\&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где m - это действительное число не меньше единицы, &amp;lt;math&amp;gt;u_{i,j}&amp;lt;/math&amp;gt; - коэффициент принадлежности вектора &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;c_{j}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; - &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый компонент &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;-мерного вектора &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;c_{j}&amp;lt;/math&amp;gt;&lt;br /&gt;
- центр &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-ого кластера, а &amp;lt;math&amp;gt;\left\Vert{*}\right\|&amp;lt;/math&amp;gt; - это любая норма, определяющая расстояние от вектора до центра кластера.&lt;br /&gt;
Нечёткое разбиение входных данных на кластеры производится итеративной оптимизацией вышеуказанной функции с обновлением коэффициента принадлежности &amp;lt;math&amp;gt;u_{i,j}&amp;lt;/math&amp;gt; и переопределением центра кластера &amp;lt;math&amp;gt;c_{j}&amp;lt;/math&amp;gt; на каждой итерации алгоритма.&lt;br /&gt;
&lt;br /&gt;
==== Вычисляемые данные на каждой итерации ====&lt;br /&gt;
* Центры кластеров рассчитываются по следующей формуле: &amp;lt;math&amp;gt;c_{j} = {{\sum_{i = 1}^{n}{u_{i,j}^m} * x_{i}} \over {\sum_{i = 1}^{n}{u_{i,j}^m}}}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;u_{i,j}&amp;lt;/math&amp;gt; — коэффициент принадлежности &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; вектора к кластеру &amp;lt;math&amp;gt;c_{j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Коэффициент принадлежности рассчитывается по формуле: &amp;lt;math&amp;gt;u_{i,j} = {1 \over \sum_{k = 1}^{C}{({\left\Vert{x_{i}-c_{j}}\right\| \over \left\Vert{x_{i}-c_{k}}\right\|})}^{2 \over m-1}}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Решающая функция рассчитывается по формуле: &amp;lt;math&amp;gt;\max_{i,j}(|u_{i,j}^{(k)} - u_{i,j}^{(k-1)}|)&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;
&lt;br /&gt;
Ядром алгоритма является:&lt;br /&gt;
* вычисление новых центров кластеров&lt;br /&gt;
* для каждого входного вектора вычисление Евклидова расстояния до центров кластеров, а также коэффициента принадлежности кластерам&lt;br /&gt;
* вычисление решающей функции&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
В каждой итерации алгоритма происходит 3 основных действия описанных в п. 1.2.1:&lt;br /&gt;
*вычисление центров кластеров&lt;br /&gt;
*вычисление коэффициентов принадлежности&lt;br /&gt;
*вычисление решающей функции&lt;br /&gt;
Подробное описание макроструктур в виде кода приведено в пункте 1.5&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Схему реализации последовательного алгоритма можно описать на C++ следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
FCM (X[], C, m, eps){&lt;br /&gt;
    float deside = 0;&lt;br /&gt;
    float newDeside = 0;&lt;br /&gt;
    generateMembershipDegree();            //заполняет uPrev[][] случайными нормрованными коэффициентами&lt;br /&gt;
    while (true){&lt;br /&gt;
        newDeside = deside;&lt;br /&gt;
&lt;br /&gt;
        //вычисление центров кластеров&lt;br /&gt;
        for (int j=0; j&amp;lt;C; j++){           //для каждого кластера&lt;br /&gt;
            float numerator = 0;&lt;br /&gt;
            float denumerator = 0;&lt;br /&gt;
            for (int i=0; i&amp;lt;X.size(); i++){        //для каждого вектора&lt;br /&gt;
                numerator+=pow(u[i][j], m) * x[i];&lt;br /&gt;
                denumerator+=pow(u[i][j], m);&lt;br /&gt;
            }&lt;br /&gt;
            c[j] = numerator / denumerator;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        //вычисление коэффициентов u[][]&lt;br /&gt;
        for (int i=0; i&amp;lt;X.size(); i++)    //для каждого вектора&lt;br /&gt;
            for (int j=0; j&amp;lt;C; j++){   //для каждого кластера&lt;br /&gt;
                sum = 0;&lt;br /&gt;
                for (int k=0; k&amp;lt;C; k++)&lt;br /&gt;
                    sum+= pow( dist(x[i], c[j]) / dist(x[i], c[k]), 2/(m-1));&lt;br /&gt;
                u[i][j] = 1/sum&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
        //определения максимального различия между u[][] и uPrev[][]&lt;br /&gt;
        float max = 0;&lt;br /&gt;
        for (int i=0; i&amp;lt;X.size(); i++)    //для каждого вектора&lt;br /&gt;
            for (int j=0; j&amp;lt;C; j++){   //для каждого кластера&lt;br /&gt;
                if (abs(uPrev[i][j]-u[i][j])&amp;gt;max)&lt;br /&gt;
                    max = abs(uPrev[i][j]-u[i][j]);&lt;br /&gt;
&lt;br /&gt;
        if (eps &amp;lt;= max)&lt;br /&gt;
            for (int i=0; i&amp;lt;X.size(); i++)    //для каждого вектора&lt;br /&gt;
                for (int j=0; j&amp;lt;C; j++){   //для каждого кластера&lt;br /&gt;
                    uPrev[i][j]=u[i][j];&lt;br /&gt;
        else&lt;br /&gt;
            break;&lt;br /&gt;
             &lt;br /&gt;
    }&lt;br /&gt;
    return u;&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;
* параметра &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;&lt;br /&gt;
* набора входных векторов &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;&lt;br /&gt;
* выбора начальных коэффициентов &amp;lt;math&amp;gt;u&amp;lt;/math&amp;gt;&lt;br /&gt;
то в данном пункте будет приведена сложность одной итерации относительно количества входных векторов.&lt;br /&gt;
Как видно из предыдущего пункта, для вычисления центров кластеров требуется &amp;lt;math&amp;gt;O(2*C*|X|)&amp;lt;/math&amp;gt; операций, для определения коэффициентов &amp;lt;math&amp;gt;u&amp;lt;/math&amp;gt; - &amp;lt;math&amp;gt;O(C^2*|X|)&amp;lt;/math&amp;gt; операций, а для вычисления решающей функции - &amp;lt;math&amp;gt;O(2*C*|X|)&amp;lt;/math&amp;gt; операций, где &amp;lt;math&amp;gt;|X|&amp;lt;/math&amp;gt; -  число входных векторов, а &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; - количество кластеров.&lt;br /&gt;
&lt;br /&gt;
Таким образом итоговая сложность одной итерации составляет &amp;lt;math&amp;gt;O(C^2*|X|)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
&lt;br /&gt;
Как видно из пункта 1.5, на каждом действии каждой итерации алгоритма все операции, выполняющиеся в цикле, не зависят друг от друга и могут быть распараллелены. Это показано на Рисунке 1.&lt;br /&gt;
&lt;br /&gt;
[[File:FCMIG.png|thumb|center|1200px|Рисунок 1. Информационный граф алгоритма. (1)-(7) - это наборы последовательных действий (например, (2) - последовательные операции деления, взятия адреса и присваивания).]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
На каждом ярусе ярусно-параллельной формы алгоритма будет располагаться конечное число элементарных операций, например, взятие адреса, сложение или возведение в степень. Информационый граф из п.1.7 изображает свёрнутую ярусно-параллельную форму алгоритма. &lt;br /&gt;
&lt;br /&gt;
Сложность алгоритма будем рассчитывать в предположении, что число вычислительных ядер стремится к бесконечности. Как видно из информационного графа, параллельная сложность вычисления центров кластеров составляет &amp;lt;math&amp;gt;O(\log_{2} C*|X|)&amp;lt;/math&amp;gt;, вычисления коэффициентов принадлежности - &amp;lt;math&amp;gt;O(\log_{2} C^2*|X|)&amp;lt;/math&amp;gt;, а вычисления решающей функции - не больше чем &amp;lt;math&amp;gt;O(\log_{2} C*|X|)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Таким образом параллельная сложность итерации алгоритма составляет &amp;lt;math&amp;gt;O(\log_{2} C^4*|X|^3)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Так как задачи, решаемые в макроструктуре алгоритма могут быть сведены к задачам вычисления суммы элементов массива и максимального элемента массива, то на &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом ярусе графа будет находиться &amp;lt;math&amp;gt;{N}\over{2^i}&amp;lt;/math&amp;gt; операции, где N - количество элементов массива.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
==== Входные данные алгоритма ====&lt;br /&gt;
* &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;|X|&amp;lt;/math&amp;gt; входных векторов длины &amp;lt;math&amp;gt;p&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;m&amp;lt;/math&amp;gt; - коэффициент неопределённости&lt;br /&gt;
* &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - коэффициент, определяющий точность алгоритма.&lt;br /&gt;
&lt;br /&gt;
Объем входных данных: &amp;lt;math&amp;gt;|X|*p+3&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Выходные данные алгоритма ====&lt;br /&gt;
* &amp;lt;math&amp;gt;u&amp;lt;/math&amp;gt; - матрица принадлежности векторов кластерам&lt;br /&gt;
&lt;br /&gt;
Объем выходных данных: &amp;lt;math&amp;gt;|X|*C&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Увеличение скорости работы алгоритма при распараллеливании на бесконечном количестве процессоров составляет &amp;lt;math&amp;gt;O({{C^2*|X|}\over{\log_{2} (C^4*|X|^3)}})&amp;lt;/math&amp;gt;. Например, для разбиения 1000 элементов на 10 кластеров производительность параллельного алгоритма будет в 2315 раз больше, а на 20 кластеров - уже в 8477 раз.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
&lt;br /&gt;
Как видно из предыдущих пунктов, масштабируется данный алгоритм хорошо. С увеличением количества процессоров время работы падает, а с увеличением количества входных данных и количества кластеров - растёт. &lt;br /&gt;
На рисунках показаны результаты запусков алгоритма на разном количестве входных данных и процессоров на массивно-параллельной вычислительной системе Blue Gene/P. Использовался компилятор mpixlcxx без указания специфических опций. Запуски производились в режиме SMP (на каждом ядре 1 MPI процесс из 4 SMP нитей, 2 Гб памяти). Характеристики вычислительного узла: 4 ядерный 32-битный процессор PowerPC 850 Мгц.&lt;br /&gt;
&lt;br /&gt;
Исходных код программы можно найти здесь: https://github.com/demonsmd/superPrak&lt;br /&gt;
[[File:FCMvectors_color2.png|thumb|center|1250px|Рисунок 2. Масштабируемость алгоритма. Зависимость времени работы алгоритма от количества процессоров и входных данных при фиксированном количестве кластеров.]]&lt;br /&gt;
[[File:FCMclusters_color.png|thumb|center|1250px|Рисунок 3. Масштабируемость алгоритма. Зависимость времени работы алгоритма от количества процессоров и кластеров при фиксированном количестве входных данных.]]&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Существует множество реализаций данного алгоритма. Рассмотрим некоторые из них:&lt;br /&gt;
&lt;br /&gt;
- Например, тут: https://habrahabr.ru/post/208496/&lt;br /&gt;
&amp;lt;ref&amp;gt;Нестер А. &amp;quot;Алгоритм нечёткой кластеризации fuzzy c-means на PHP&amp;quot;. [html](https://habrahabr.ru/post/208496/)&amp;lt;/ref&amp;gt;&lt;br /&gt;
приведено краткое описание алгоритма и приведена его реализация на php. В данной статье довольно подробно расписан каждый шаг алгоритма и приведён соответствующий ему фрагмент кода.&lt;br /&gt;
&lt;br /&gt;
- Тут: http://num-meth.srcc.msu.ru/zhurnal/tom_2012/v13r207.html&lt;br /&gt;
&amp;lt;ref&amp;gt;Миниахметов Р.М., Цымблер М.Л. &amp;quot;Интеграция алгоритма кластеризации Fuzzy c-Means в PostgreSQL&amp;quot;. [html](http://num-meth.srcc.msu.ru/zhurnal/tom_2012/v13r207.html)&amp;lt;/ref&amp;gt;&lt;br /&gt;
приводится реализация алгоритма для PostgreSQL, а также прилагается скрипт внедрения алгоритма.&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;/div&gt;</summary>
		<author><name>Coctic</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:Coctic&amp;diff=19653</id>
		<title>Участник:Coctic</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:Coctic&amp;diff=19653"/>
		<updated>2016-11-30T14:49:35Z</updated>

		<summary type="html">&lt;p&gt;Coctic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Константин Стефанов, к.ф.-м.н. с.н.с. лаб. параллельных информационных технологий НИВЦ МГУ&lt;/div&gt;</summary>
		<author><name>Coctic</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:Coctic&amp;diff=19652</id>
		<title>Участник:Coctic</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:Coctic&amp;diff=19652"/>
		<updated>2016-11-30T14:48:48Z</updated>

		<summary type="html">&lt;p&gt;Coctic: Новая страница: «Константин Стефанов, с.н.с. лаб. параллельных информационных технологий НИВЦ МГУ»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Константин Стефанов, с.н.с. лаб. параллельных информационных технологий НИВЦ МГУ&lt;/div&gt;</summary>
		<author><name>Coctic</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:Demon_smd/%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=19335</id>
		<title>Участник:Demon smd/Нечеткий алгоритм С средних</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:Demon_smd/%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=19335"/>
		<updated>2016-11-28T07:32:45Z</updated>

		<summary type="html">&lt;p&gt;Coctic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних (Fuzzy C-means)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(C^2*N*D*IterNumber)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(\log_{2}C^4*|X|^3) * IterNumber&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(C^2*|X|)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;|X|*p&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; - размерность входных векторов&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;|X|*C &amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы описания алгоритма: &lt;br /&gt;
[[Участник:Demon smd|Д.А.Гуськов]] &lt;br /&gt;
[[Участник:marina abramenkova|М.А.Абраменкова]]&lt;br /&gt;
Во все разделы вклад равноценный.&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
Нечёткий алгоритм кластеризации С-средних был разработан (для случая m=2) J.C. Dunn в 1973 г. &lt;br /&gt;
&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; &lt;br /&gt;
и усовершенствован (для случая m&amp;gt;1) &lt;br /&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;
. В отличие от алгоритма c-means данный метод кластеризации предполагает, что входные данные могут принадлежать более, чем одному кластеру одновременно.&lt;br /&gt;
Алгоритм получает на вход набор кластеризуемых векторов, количество кластеров, коэффициент неопределённости m и коэффициент &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;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;
=== Математическое описание алгоритма ===&lt;br /&gt;
Нечеткий алгоритм С средних минимизирует величину:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
J_{m} = \sum_{i = 1}^{N}\sum_{j = 1}^{C}u_{i,j}^m\left\Vert{x_{i}-c_{j}}\right\|^2 &amp;amp; , &amp;amp; &amp;amp;  1 \le m \le \infty , \\&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где m - это действительное число не меньше единицы, &amp;lt;math&amp;gt;u_{i,j}&amp;lt;/math&amp;gt; - коэффициент принадлежности вектора &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;c_{j}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; - &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый компонент &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;-мерного вектора &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;c_{j}&amp;lt;/math&amp;gt;&lt;br /&gt;
- центр &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-ого кластера, а &amp;lt;math&amp;gt;\left\Vert{*}\right\|&amp;lt;/math&amp;gt; - это любая норма, определяющая расстояние от вектора до центра кластера.&lt;br /&gt;
Нечёткое разбиение входных данных на кластеры производится итеративной оптимизацией вышеуказанной функции с обновлением коэффициента принадлежности &amp;lt;math&amp;gt;u_{i,j}&amp;lt;/math&amp;gt; и переопределением центра кластера &amp;lt;math&amp;gt;c_{j}&amp;lt;/math&amp;gt; на каждой итерации алгоритма.&lt;br /&gt;
&lt;br /&gt;
==== Вычисляемые данные на каждой итерации ====&lt;br /&gt;
* Центры кластеров рассчитываются по следующей формуле: &amp;lt;math&amp;gt;c_{j} = {{\sum_{i = 1}^{n}{u_{i,j}^m} * x_{i}} \over {\sum_{i = 1}^{n}{u_{i,j}^m}}}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;u_{i,j}&amp;lt;/math&amp;gt; — коэффициент принадлежности &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; вектора к кластеру &amp;lt;math&amp;gt;c_{j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Коэффициент принадлежности рассчитывается по формуле: &amp;lt;math&amp;gt;u_{i,j} = {1 \over \sum_{k = 1}^{C}{({\left\Vert{x_{i}-c_{j}}\right\| \over \left\Vert{x_{i}-c_{k}}\right\|})}^{2 \over m-1}}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Решающая функция рассчитывается по формуле: &amp;lt;math&amp;gt;\max_{i,j}(|u_{i,j}^{(k)} - u_{i,j}^{(k-1)}|)&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;
&lt;br /&gt;
Ядром алгоритма является:&lt;br /&gt;
* вычисление новых центров кластеров&lt;br /&gt;
* для каждого входного вектора вычисление Евклидова расстояния до центров кластеров, а также коэффициента принадлежности кластерам&lt;br /&gt;
* вычисление решающей функции&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
В каждой итерации алгоритма происходит 3 основных действия описанных в п. 1.2.1:&lt;br /&gt;
*вычисление центров кластеров&lt;br /&gt;
*вычисление коэффициентов принадлежности&lt;br /&gt;
*вычисление решающей функции&lt;br /&gt;
Подробное описание макроструктур в виде кода приведено в пункте 1.5&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Схему реализации последовательного алгоритма можно описать на C++ следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
FCM (X[], C, m, eps){&lt;br /&gt;
    float deside = 0;&lt;br /&gt;
    float newDeside = 0;&lt;br /&gt;
    generateMembershipDegree();            //заполняет uPrev[][] случайными нормрованными коэффициентами&lt;br /&gt;
    while (true){&lt;br /&gt;
        newDeside = deside;&lt;br /&gt;
&lt;br /&gt;
        //вычисление центров кластеров&lt;br /&gt;
        for (int j=0; j&amp;lt;C; j++){           //для каждого кластера&lt;br /&gt;
            float numerator = 0;&lt;br /&gt;
            float denumerator = 0;&lt;br /&gt;
            for (int i=0; i&amp;lt;X.size(); i++){        //для каждого вектора&lt;br /&gt;
                numerator+=pow(u[i][j], m) * x[i];&lt;br /&gt;
                denumerator+=pow(u[i][j], m);&lt;br /&gt;
            }&lt;br /&gt;
            c[j] = numerator / denumerator;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        //вычисление коэффициентов u[][]&lt;br /&gt;
        for (int i=0; i&amp;lt;X.size(); i++)    //для каждого вектора&lt;br /&gt;
            for (int j=0; j&amp;lt;C; j++){   //для каждого кластера&lt;br /&gt;
                sum = 0;&lt;br /&gt;
                for (int k=0; k&amp;lt;C; k++)&lt;br /&gt;
                    sum+= pow( dist(x[i], c[j]) / dist(x[i], c[k]), 2/(m-1));&lt;br /&gt;
                u[i][j] = 1/sum&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
        //определения максимального различия между u[][] и uPrev[][]&lt;br /&gt;
        float max = 0;&lt;br /&gt;
        for (int i=0; i&amp;lt;X.size(); i++)    //для каждого вектора&lt;br /&gt;
            for (int j=0; j&amp;lt;C; j++){   //для каждого кластера&lt;br /&gt;
                if (abs(uPrev[i][j]-u[i][j])&amp;gt;max)&lt;br /&gt;
                    max = abs(uPrev[i][j]-u[i][j]);&lt;br /&gt;
&lt;br /&gt;
        if (eps &amp;lt;= max)&lt;br /&gt;
            for (int i=0; i&amp;lt;X.size(); i++)    //для каждого вектора&lt;br /&gt;
                for (int j=0; j&amp;lt;C; j++){   //для каждого кластера&lt;br /&gt;
                    uPrev[i][j]=u[i][j];&lt;br /&gt;
        else&lt;br /&gt;
            break;&lt;br /&gt;
             &lt;br /&gt;
    }&lt;br /&gt;
    return u;&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;
* параметра &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;&lt;br /&gt;
* набора входных векторов &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;&lt;br /&gt;
* выбора начальных коэффициентов &amp;lt;math&amp;gt;u&amp;lt;/math&amp;gt;&lt;br /&gt;
то в данном пункте будет приведена сложность одной итерации относительно количества входных векторов.&lt;br /&gt;
Как видно из предыдущего пункта, для вычисления центров кластеров требуется &amp;lt;math&amp;gt;O(2*C*|X|)&amp;lt;/math&amp;gt; операций, для определения коэффициентов &amp;lt;math&amp;gt;u&amp;lt;/math&amp;gt; - &amp;lt;math&amp;gt;O(C^2*|X|)&amp;lt;/math&amp;gt; операций, а для вычисления решающей функции - &amp;lt;math&amp;gt;O(2*C*|X|)&amp;lt;/math&amp;gt; операций, где &amp;lt;math&amp;gt;|X|&amp;lt;/math&amp;gt; -  число входных векторов, а &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; - количество кластеров.&lt;br /&gt;
&lt;br /&gt;
Таким образом итоговая сложность одной итерации составляет &amp;lt;math&amp;gt;O(C^2*|X|)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
&lt;br /&gt;
Как видно из пункта 1.5, на каждом действии каждой итерации алгоритма все операции, выполняющиеся в цикле, не зависят друг от друга и могут быть распараллелены. Это показано на Рисунке 1.&lt;br /&gt;
&lt;br /&gt;
[[File:FCMIG.png|thumb|center|1200px|Рисунок 1. Информационный граф алгоритма. (1)-(7) - это наборы последовательных действий (например, (2) - последовательные операции деления, взятия адреса и присваивания).]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
На каждом ярусе ярусно-параллельной формы алгоритма будет располагаться конечное число элементарных операций, например, взятие адреса, сложение или возведение в степень. Информационый граф из п.1.7 изображает свёрнутую ярусно-параллельную форму алгоритма. &lt;br /&gt;
&lt;br /&gt;
Сложность алгоритма будем рассчитывать в предположении, что число вычислительных ядер стремится к бесконечности. Как видно из информационного графа, параллельная сложность вычисления центров кластеров составляет &amp;lt;math&amp;gt;O(\log_{2} C*|X|)&amp;lt;/math&amp;gt;, вычисления коэффициентов принадлежности - &amp;lt;math&amp;gt;O(\log_{2} C^2*|X|)&amp;lt;/math&amp;gt;, а вычисления решающей функции - не больше чем &amp;lt;math&amp;gt;O(\log_{2} C*|X|)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Таким образом параллельная сложность итерации алгоритма составляет &amp;lt;math&amp;gt;O(\log_{2} C^4*|X|^3)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Так как задачи, решаемые в макроструктуре алгоритма могут быть сведены к задачам вычисления суммы элементов массива и максимального элемента массива, то на &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом ярусе графа будет находиться &amp;lt;math&amp;gt;{N}\over{2^i}&amp;lt;/math&amp;gt; операции, где N - количество элементов массива.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
==== Входные данные алгоритма ====&lt;br /&gt;
* &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;|X|&amp;lt;/math&amp;gt; входных векторов длины &amp;lt;math&amp;gt;p&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;m&amp;lt;/math&amp;gt; - коэффициент неопределённости&lt;br /&gt;
* &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - коэффициент, определяющий точность алгоритма.&lt;br /&gt;
&lt;br /&gt;
Объем входных данных: &amp;lt;math&amp;gt;|X|*p+3&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Выходные данные алгоритма ====&lt;br /&gt;
* &amp;lt;math&amp;gt;u&amp;lt;/math&amp;gt; - матрица принадлежности векторов кластерам&lt;br /&gt;
&lt;br /&gt;
Объем выходных данных: &amp;lt;math&amp;gt;|X|*C&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Увеличение скорости работы алгоритма при распараллеливании на бесконечном количестве процессоров составляет &amp;lt;math&amp;gt;O({{C^2*|X|}\over{\log_{2} (C^4*|X|^3)}})&amp;lt;/math&amp;gt;. Например, для разбиения 1000 элементов на 10 кластеров производительность параллельного алгоритма будет в 2315 раз больше, а на 20 кластеров - уже в 8477 раз.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
&lt;br /&gt;
Как видно из предыдущих пунктов, масштабируется данный алгоритм хорошо. С увеличением количества процессоров время работы падает, а с увеличением количества входных данных и количества кластеров - растёт. На рисунках показаны результаты запусков алгоритма на разном количестве входных данных и процессоров на Blue Gene/P. Исходных код программы можно найти здесь: https://github.com/demonsmd/superPrak&lt;br /&gt;
[[File:FCMvectors.png|thumb|center|1500px|Рисунок 2. Масштабируемость алгоритма. Зависимость сложности алгоритма от количества процессоров и входных данных при фиксированном количестве кластеров.]]&lt;br /&gt;
[[File:FCMclusters.png|thumb|center|1500px|Рисунок 3. Масштабируемость алгоритма. Зависимость сложности алгоритма от количества процессоров и кластеров при фиксированном количестве входных данных.]]&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Существует множество реализаций данного алгоритма. Рассмотрим некоторые из них:&lt;br /&gt;
&lt;br /&gt;
- Например, тут: https://habrahabr.ru/post/208496/&lt;br /&gt;
&amp;lt;ref&amp;gt;Нестер А. &amp;quot;Алгоритм нечёткой кластеризации fuzzy c-means на PHP&amp;quot;. [html](https://habrahabr.ru/post/208496/)&amp;lt;/ref&amp;gt;&lt;br /&gt;
приведено краткое описание алгоритма и приведена его реализация на php. В данной статье довольно подробно расписан каждый шаг алгоритма и приведён соответствующий ему фрагмент кода.&lt;br /&gt;
&lt;br /&gt;
- Тут: http://num-meth.srcc.msu.ru/zhurnal/tom_2012/v13r207.html&lt;br /&gt;
&amp;lt;ref&amp;gt;Миниахметов Р.М., Цымблер М.Л. &amp;quot;Интеграция алгоритма кластеризации Fuzzy c-Means в PostgreSQL&amp;quot;. [html](http://num-meth.srcc.msu.ru/zhurnal/tom_2012/v13r207.html)&amp;lt;/ref&amp;gt;&lt;br /&gt;
приводится реализация алгоритма для PostgreSQL, а также прилагается скрипт внедрения алгоритма.&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;/div&gt;</summary>
		<author><name>Coctic</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Demon_smd&amp;diff=19334</id>
		<title>Обсуждение участника:Demon smd</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Demon_smd&amp;diff=19334"/>
		<updated>2016-11-28T07:32:32Z</updated>

		<summary type="html">&lt;p&gt;Coctic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Статья [[Нечеткий алгоритм С средних]] =&lt;br /&gt;
* не указан вклад каждого автора [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:58, 25 октября 2016 (MSK) - исправлено&lt;br /&gt;
:: Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:29, 31 октября 2016 (MSK)&lt;br /&gt;
* п. 1.9 не приведены оценки объема входных и выходных данных [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:58, 25 октября 2016 (MSK) - исправлено&lt;br /&gt;
:: Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:29, 31 октября 2016 (MSK)&lt;br /&gt;
* п. 2.4. Не приведена ссылка на текст исследуемой программы [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 18:28, 16 ноября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:32, 28 ноября 2016 (MSK)&lt;br /&gt;
* п. 2.4. Не указана аппаратная платформа, на которой проводилось тестирование [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 18:28, 16 ноября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:32, 28 ноября 2016 (MSK)&lt;br /&gt;
* п. 2.4. На рис. 2 и 3 подпись вертикальной оси накладывается на подписи шкалы  [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 18:28, 16 ноября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:32, 28 ноября 2016 (MSK)&lt;br /&gt;
* п. 2.4. Не приведено никаких сведений о масштабируемости исследуемой программы. На рис. 2 и 3 приведены графики зависимости некоей &amp;quot;сложности&amp;quot; (какя сложность имеется в виду - не указано) от разных параметров. Как из этих графиков извлечь сведения о масштабируемости - не указано. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 18:28, 16 ноября 2016 (MSK)&lt;br /&gt;
** Исправлено частично. В осях стало время в секундах, в подписях к рисункам по-прежнему непонятная &amp;quot;сложность&amp;quot;. Что в итоге на рисунках - неясно. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:32, 28 ноября 2016 (MSK)&lt;br /&gt;
* Графики на рис. 2 и 3 плохо читаются [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:32, 28 ноября 2016 (MSK)&lt;br /&gt;
* Необходимо указать характеристики программно-аппаратной платформы (какой компилятор, с какими опциями использовался, какие версии библиотек, на каких узлах проводился запуск и т.д.) [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:32, 28 ноября 2016 (MSK)&lt;/div&gt;</summary>
		<author><name>Coctic</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Darel&amp;diff=19001</id>
		<title>Обсуждение участника:Darel</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Darel&amp;diff=19001"/>
		<updated>2016-11-23T10:18:17Z</updated>

		<summary type="html">&lt;p&gt;Coctic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Статья [[Участник:Ян-Мартин Тамм/Строгий алгоритм С средних]] =&lt;br /&gt;
* Отсутствует указание автора [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:17, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:58, 31 октября 2016 (MSK)&lt;br /&gt;
* Пропущен пункт 1.1 &amp;quot;общее описание алгоритма&amp;quot;, у следующих пунктов сместилась нумерация [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:17, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:58, 31 октября 2016 (MSK)&lt;br /&gt;
* п. 1.6 на рисунках приведены схема алгоритма и его блока, информационного графа не приведено [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:17, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:58, 31 октября 2016 (MSK)&lt;br /&gt;
----------------------&lt;br /&gt;
* Названия частей 1 и 2 не соответствуют шаблону [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:58, 31 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:02, 8 ноября 2016 (MSK)&lt;br /&gt;
* В списке литературы у первой ссылки отсутствуют выходные данные, по которым можно однозначно идентифицировать источник [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:17, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:02, 8 ноября 2016 (MSK)&lt;br /&gt;
* Отсутствует п. 2.4. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 16:55, 16 ноября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 14:15, 18 ноября 2016 (MSK)&lt;br /&gt;
* П. 2.4. Необходимо добавить описание ключей компилятора, особенностей запуска (раздел, используемые вычислительные узлы и т.п. информация, достаточная для воспроизведения данных). [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 14:15, 18 ноября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:18, 23 ноября 2016 (MSK)&lt;/div&gt;</summary>
		<author><name>Coctic</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:%D0%AF%D0%BD-%D0%9C%D0%B0%D1%80%D1%82%D0%B8%D0%BD_%D0%A2%D0%B0%D0%BC%D0%BC/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%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=19000</id>
		<title>Участник:Ян-Мартин Тамм/Строгий алгоритм С средних</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:%D0%AF%D0%BD-%D0%9C%D0%B0%D1%80%D1%82%D0%B8%D0%BD_%D0%A2%D0%B0%D0%BC%D0%BC/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%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=19000"/>
		<updated>2016-11-23T10:18:00Z</updated>

		<summary type="html">&lt;p&gt;Coctic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|{{REVISIONUSER}}}}&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Строгий алгоритм С средних (K-means, Hard C-Means)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(nkdi)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(log_2(k)log_2(d)i)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(nkd)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;nd+1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;nk&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
Автор: [[Участник:Darel|Ян-Мартин Тамм]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритма =&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&amp;lt;b&amp;gt;Строгий алгоритм C средних&amp;lt;/b&amp;gt;, более известный как &amp;lt;b&amp;gt;K-средних&amp;lt;/b&amp;gt;, решает задачу разделения векторов в многомерном пространстве на заданное количество кластеров. При этом каждый вектор принадлежит только одному кластеру, поэтому алгоритм называется строгим, в то время как нечеткий алгоритм C средних (Fuzzy C-means, Soft K-means) определяет степень принадлежности вектора каждому из кластеров.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Данная задача является NP-трудной, тем не менее описываемый алгоритм сходится к локальному оптимуму. Глобальный оптимум не гарантируется и зависит от первоначального распределения центров кластеров и их количества. &amp;lt;br&amp;gt;Общая идея алгоритма такова: фиксируем число кластеров &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;, произвольным образом выбираем центры кластеров, после чего повторяем следующие два действия, пока не будет выполнено условие остановки:&lt;br /&gt;
#Распределяем каждый вектор в ближайший кластер&lt;br /&gt;
#Пересчитываем значения центров как среднее значение координат векторов в каждом кластере&lt;br /&gt;
Минимизируется сумма расстояний векторов от центров их кластеров. Остановка производится если либо значение данной функции становится ниже некоторого порога, либо мало изменяется по сравнению с предыдущей итерацией.&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Дано множество d-мерных векторов &amp;amp;nbsp;&amp;lt;math&amp;gt;U=\{u_1, u_2, ..., u_n\}&amp;lt;/math&amp;gt; и число кластеров &amp;lt;math&amp;gt;k \in \mathbb{N}&amp;lt;/math&amp;gt;. Требуется разбить множество &amp;lt;math&amp;gt;U&amp;lt;/math&amp;gt; на &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; непересекающихся непустых кластеров &amp;lt;math&amp;gt;C_1, C_2, ..., C_k&amp;lt;/math&amp;gt; таких, что &amp;lt;math&amp;gt;{\bigcup \limits _{i = 1}^k C_i} = U &amp;lt;/math&amp;gt;. &lt;br /&gt;
&amp;lt;br&amp;gt;Для этого минимизируется функция &amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^k J_i = \sum\limits_{i=1}^k \sum\limits_{ u \in C_i} \|u-c_i \|^2 &lt;br /&gt;
&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;c_i&amp;lt;/math&amp;gt;— центр масс векторов кластера &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Произвольным образом инициализируем центры кластеров &amp;lt;math&amp;gt;c_1, c_2, ..., c_k&amp;lt;/math&amp;gt;, после чего начинается основная часть алгоритма.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&amp;lt;li&amp;gt;Каждый вектор &amp;lt;math&amp;gt;u_l&amp;lt;/math&amp;gt; определяем в ближайший к нему кластер &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt;, то есть такой, что &lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\|u_l-c_i\|^2 \leqslant \|u_l-c_j\|^2 \;\; \forall i \neq j; \;\; (i,j=1,2,\ldots,k, \; l = 1,2,\ldots,n)&lt;br /&gt;
&amp;lt;/math&amp;gt;.&amp;lt;/li&amp;gt; Хранить информацию о принадлежности векторов кластерам будем в матрице &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; следующего вида:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ij} = \begin{cases}&lt;br /&gt;
1, &amp;amp; u_j \in C_i \\&lt;br /&gt;
0, &amp;amp; \text{otherwise}&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Считаем значение функции &amp;lt;math&amp;gt;J&amp;lt;/math&amp;gt; и прекращаем работу алгоритма, если это значение меньше заданного порога &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;, либо значение мало изменилось после текущей итерации.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Обновляем значения центров кластеров&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{u \in C_i} u \;\; (i=1,2,\ldots,k)&lt;br /&gt;
&amp;lt;/math&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Возвращаемся к распределению векторов по кластерам.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительным ядром алгоритма является весь алгоритм, а именно два основных его шага:&lt;br /&gt;
&amp;lt;ul&amp;gt;&amp;lt;li&amp;gt;Распределение векторов по кластерам&amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;Пересчёт центров кластеров&amp;lt;/li&amp;gt;&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как уже говорилось раньше, первоначальное распределение векторов по кластерам может быть произвольным, например, можно случайным образом выбрать &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; векторов из множества всех векторов &amp;lt;math&amp;gt;U&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Далее начинается цикл, его первая операция — распределение векторов по кластерам. В ней для каждого вектора считается расстояние от него, до каждого кластера &amp;lt;math&amp;gt;\rho = \big \| u - c \big \|^2=\sum_{i=1}^d (u_i-c_i)^2&amp;lt;/math&amp;gt;, после чего из них выбирается наименьшее и заносится в матрицу.&amp;lt;br&amp;gt;Подсчёт функции &amp;lt;math&amp;gt;J&amp;lt;/math&amp;gt; можно проводить одновременно с первым шагом, так как в ней суммируются те же самые расстояния.&amp;lt;br&amp;gt;Пересчёт центров кластеров — сумма всех векторов кластера, делённая на количество объектов в кластере. &amp;lt;math&amp;gt;&lt;br /&gt;
c = \frac{1}{|C|} \sum\limits_{u \in C} u&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def kmeans(points, k, cutoff):&lt;br /&gt;
    &lt;br /&gt;
    # Pick out k random points to use as our initial centroids&lt;br /&gt;
    initial = random.sample(points, k)&lt;br /&gt;
    &lt;br /&gt;
    # Create k clusters using those centroids&lt;br /&gt;
    clusters = [Cluster([p]) for p in initial]&lt;br /&gt;
    &lt;br /&gt;
    # Loop through the dataset until the clusters stabilize&lt;br /&gt;
    while True:&lt;br /&gt;
        # Create a list of lists to hold the points in each cluster&lt;br /&gt;
        lists = [ [] for c in clusters]&lt;br /&gt;
&lt;br /&gt;
        # For every point in the dataset ...&lt;br /&gt;
        for p in points:&lt;br /&gt;
            # Get the distance between that point and the centroid of the first cluster.&lt;br /&gt;
            smallest_distance = getDistance(p, clusters[0].centroid)&lt;br /&gt;
        &lt;br /&gt;
            # Set the cluster this point belongs to&lt;br /&gt;
            clusterIndex = 0&lt;br /&gt;
        &lt;br /&gt;
            # For the remainder of the clusters ...&lt;br /&gt;
            for i in range(clusterCount - 1):&lt;br /&gt;
                # calculate the distance of that point to each other cluster&#039;s centroid&lt;br /&gt;
                distance = getDistance(p, clusters[i+1].centroid)&lt;br /&gt;
                # If it&#039;s closer to that cluster&#039;s centroid update what we&lt;br /&gt;
                # think the smallest distance is, and set the point to belong to that cluster&lt;br /&gt;
                if distance &amp;lt; smallest_distance:&lt;br /&gt;
                    smallest_distance = distance&lt;br /&gt;
                    clusterIndex = i+1&lt;br /&gt;
            lists[clusterIndex].append(p)&lt;br /&gt;
        &lt;br /&gt;
        # Set our total_shift to zero for this iteration&lt;br /&gt;
        total_shift = 0.0&lt;br /&gt;
        &lt;br /&gt;
        # As many times as there are clusters ...&lt;br /&gt;
        for i in range(k):&lt;br /&gt;
            # Calculate how far the centroid moved in this iteration&lt;br /&gt;
            shift = clusters[i].update(lists[i])&lt;br /&gt;
            # Keep track of the total moves from all cluster centroid updates&lt;br /&gt;
            total_shift += shift&lt;br /&gt;
        &lt;br /&gt;
        # If the centroids have stopped moving much, we&#039;re done!&lt;br /&gt;
        if total_shift &amp;lt; cutoff:&lt;br /&gt;
            break&lt;br /&gt;
    return clusters&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Распределение по кластерам — для каждого из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов и каждого из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; кластеров посчитать расстояние, сложив &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; раз значения, на вычисление каждого из которых нужно 2 операции —&amp;amp;nbsp;&amp;lt;math&amp;gt;O(nkd)&amp;lt;/math&amp;gt;. Пересчёт центров — &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; раз сложить и &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; раз поделить — &amp;amp;nbsp;&amp;lt;math&amp;gt;O(n+k)&amp;lt;/math&amp;gt;. На завершение алгоритма понадобится &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; итераций. Итого сложность &amp;lt;math&amp;gt;O(nkdi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
На рисунке ниже приведён информационный граф алгоритма.&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:HCM graph1.png]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Блок, определяющий ближайший кластер, подробнее.&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:HCM_dist1.png]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Самой трудоёмкой операцией является распределение по кластерам. Так, для рассчёта расстояний, можно провести суммирование &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; элементов за &amp;lt;math&amp;gt;log_2(d)&amp;lt;/math&amp;gt; операций. Расстояние от данного вектора до всех кластеров можно найти за одну операцию, после чего нужно найти наименьшее значение из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; элементов за &amp;lt;math&amp;gt;log_2(k)&amp;lt;/math&amp;gt; операций. И всё это нужно сделать для &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов, что можно сделать параллельно за одну операцию. Для сходимости всё так же потребуется &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; итераций, общая сложность получается &amp;lt;math&amp;gt;O(log_2(k)log_2(d)i)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; &lt;br /&gt;
*&amp;lt;math&amp;gt;U=\{u_1, u_2, ..., u_n\} \subset \mathbb{R}^d&amp;lt;/math&amp;gt; — множество векторов&lt;br /&gt;
*&amp;lt;math&amp;gt;k \in \mathbb{N}&amp;lt;/math&amp;gt; — количество кластеров&lt;br /&gt;
*&amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; — порог остановки &#039;&#039;(не обязательно)&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;nd+1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
*&amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; — матрица принадлежности векторов кластерам размера &amp;lt;math&amp;gt;nk&amp;lt;/math&amp;gt;. При этом данная матрица содержит только &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; единиц, остальные значения ноль. Возможен вывод в другом виде, например, список списков.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;nk&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&amp;lt;ul&amp;gt;&amp;lt;li&amp;gt;Алгоритм не является детерминированным, так как инициализация кластеров происходит случайным образом, однако, ничто не мешает проводить инициализацию согласно некоторому детерминированному правилу.&lt;br /&gt;
&amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;Алгоритм находит локальный оптимум, поэтому его обычно запускают несколько раз и выбирают лучший результат.&amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;Вычислительная мощность &amp;lt;math&amp;gt;\frac{kdi}{k+d}&amp;lt;/math&amp;gt;&amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;Алгоритм является устойчивым при одинаковой первоначальной инициализации — малая ошибка в начальных данных или при вычислениях очень незначительно повлияют на результат (скорее всего никак не повлияют). Тем не менее, при случайной инициализации результаты будут различны.&amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;Прост в реализации и вычислениях&amp;lt;/li&amp;gt;&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Для масштабируемости использовалась следующая [http://users.eecs.northwestern.edu/~wkliao/Kmeans/index.html параллельная реализация алгоритма] с использованием MPI. Тесты были проведены на компьютерной системе [http://hpc.cmc.msu.ru/bgp BlueGene], которая включает в себя 8192 процессорных ядра и имеет пиковую производительность 27.9 терафлопс.&lt;br /&gt;
&lt;br /&gt;
Исследовалась сильная масштабируемость алгоритма. На графике видно, что алгоритм хорошо распараллеливается и достигается значительное ускорение. Рассчитывалось распределение десятимерных векторов на десять кластеров.&lt;br /&gt;
&lt;br /&gt;
Компилятор mpicc, опция -O2. Исследуемые точки: для 1024, 2048, 4096, 8192, 16384, 32768 векторов программа запускалась на 1, 2, 4, 8, 16, 32, 64, 128, 256 ядрах. Режим исполнения по умолчанию – SMP-режим, на каждый вычислительный узел один mpi процесс.&lt;br /&gt;
&lt;br /&gt;
[[Файл:HCM_BlueGene.png]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
* [http://scikit-learn.org/ scikit-learn] библиотека машинного обучения для языка Python.&lt;br /&gt;
* [https://www.scipy.org/ SciPy] библиотека на языке Python, содержащая большое число реализаций различных алгоритмов.&lt;br /&gt;
* [http://elki.dbs.ifi.lmu.de ELKI] библиотека для анализа данных на языке программирования Java, содержит различные алгоритмы кластеризации.&lt;br /&gt;
* [http://spark.apache.org/ Spark] распределённая версия алгоритма.&lt;br /&gt;
* [http://mlpack.org MLPACK] библиотека машинного обучения для C++.&lt;br /&gt;
* [http://opencv.org/ OpenCV] библиотека содержит реализацию алгоритма.&lt;br /&gt;
* [http://mahout.apache.org Apache Mahout] содержит реализацию алгоритма на базе MapReduce.&lt;br /&gt;
* [http://www.cs.waikato.ac.nz/~ml/weka Weka] библиотека и инструмент для анализа данных на языке Java.&lt;br /&gt;
* [http://torch.ch/ Torch] библиотека машинного обучения на базе языка программирования Lua.&lt;br /&gt;
* [http://www.accord-framework.net/ Accord.NET] содержит несколько различных реализаций на языке C#.&lt;br /&gt;
* [https://www.r-bloggers.com/k-means-clustering-in-r/ R k-means] реализация на языке R.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&amp;lt;ol&amp;gt;&amp;lt;li&amp;gt;[http://faculty.petra.ac.id/resmana/private/fuzzy/nfmod.pdf Jan Jantzen «Neurofuzzy Modelling».(Электронное издание)] Technical University of Denmark, Department of Automation, Bldg 326, DK-2800 Lyngby, DENMARK.&lt;br /&gt;
Tech. report no 98-H-874 (nfmod), 30 Oct 1998. &amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;Steinhaus H. (1956). Sur la division des corps materiels en parties. Bull. Acad. Polon. Sci., C1. III vol IV: 801—804.&amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;Lloyd S. (1957). Least square quantization in PCM’s. Bell Telephone Laboratories Paper.&amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;MacQueen J. (1967). Some methods for classification and analysis of multivariate observations. In Proc. 5th Berkeley Symp. on Math. Statistics and Probability, pages 281—297.&amp;lt;/li&amp;gt;&amp;lt;/ol&amp;gt;&lt;/div&gt;</summary>
		<author><name>Coctic</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:%D0%9A%D0%B0%D0%BB%D0%B5%D0%B4%D0%B0_%D0%90%D0%BB%D0%B5%D0%BA%D1%81%D0%B0%D0%BD%D0%B4%D1%80/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%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_(Hard_C-Means)&amp;diff=18999</id>
		<title>Участник:Каледа Александр/Строгий алгоритм С средних (Hard C-Means)</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:%D0%9A%D0%B0%D0%BB%D0%B5%D0%B4%D0%B0_%D0%90%D0%BB%D0%B5%D0%BA%D1%81%D0%B0%D0%BD%D0%B4%D1%80/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%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_(Hard_C-Means)&amp;diff=18999"/>
		<updated>2016-11-23T10:17:03Z</updated>

		<summary type="html">&lt;p&gt;Coctic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|{{REVISIONUSER}}}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Строгий алгоритм С средних (Hard C-Means)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;nm+1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;(n+m)C&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы описания: [[Участник:Каледа_Александр|Каледа Александр]] (разделы [[#Общее описание алгоритма|1.1]], [[#Схема реализации последовательного алгоритма|1.5]], [[#Последовательная сложность алгоритма|1.6]], [[#Информационный граф|1.7]], [[#Ресурс параллелизма алгоритма|1.8]], [[#Входные и выходные данные алгоритма|1.9]]), [[Участник:Шапулин_Андрей|Шапулин Андрей]] (разделы [[#Математическое описание алгоритма|1.2]], [[#Вычислительное ядро алгоритма|1.3]], [[#Макроструктура алгоритма|1.4]], [[#Информационный граф|1.7]], [[#Свойства алгоритма|1.10]], [[#Существующие реализации алгоритма|2.7]]).&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Строгий алгоритм C средних&#039;&#039;&#039; (&#039;&#039;&#039;&#039;&#039;Hard C-Means, HCM&#039;&#039;&#039;&#039;&#039;; &#039;&#039;Jang, Sun and Mizutani, 1997&#039;&#039;&amp;lt;ref&amp;gt;Jang, J.-S. R., Sun, C.-T. and Mizutani, E. (1997). Neuro-Fuzzy and Soft Computing, number&lt;br /&gt;
isbn 0-13-261066-3 in Matlab Curriculum Series, Prentice Hall, Upper Saddle River, NJ, USA.&amp;lt;/ref&amp;gt;) один из наиболее широко используемых алгоритмов кластеризации данных&amp;lt;ref&amp;gt;[http://faculty.petra.ac.id/resmana/private/fuzzy/nfmod.pdf Jantzen J. Neurofuzzy Modelling. 1998. Электронное издание. 28 Стр.]&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;
# Пересчёт кластерных центров.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
Исходные данные: матрица &amp;lt;math&amp;gt;U\in \mathbb{R}^{n\times m}&amp;lt;/math&amp;gt;, представляющая собой набор векторов &amp;lt;math&amp;gt;\{u_i\}_{i=1}^{n}, u_i \in \mathbb{R}^m&amp;lt;/math&amp;gt;; количество кластеров &amp;lt;math&amp;gt;C \in \mathbb{N}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные: набор векторов - кластерных центров &amp;lt;math&amp;gt;\{c_i\}_{i=1}^{C}, c_i \in \mathbb{R}^m&amp;lt;/math&amp;gt;; матрица &amp;lt;math&amp;gt;M\in \mathbb{N}^{n\times C}&amp;lt;/math&amp;gt; c информацией о разбиении объектов на кластера. Элемент &amp;lt;math&amp;gt;m_{ij}=1&amp;lt;/math&amp;gt;, если &amp;lt;math&amp;gt;u_j \in C_i&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; содержит все объекты &amp;lt;math&amp;gt;u&amp;lt;/math&amp;gt;, принадлежащие кластеру &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;. Остальные элементы &amp;lt;math&amp;gt;m_{ij}=0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм:&lt;br /&gt;
&lt;br /&gt;
Шаг 1. Инициализация кластерных центров &amp;lt;math&amp;gt;c_i, i = 1, 2, \dots, C.&amp;lt;/math&amp;gt; Это можно сделать выбрав случайным образом C векторов из входного набора &amp;lt;math&amp;gt;\{u_i\}_{i=1}^{n}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Шаг 2. Вычисление рядовой матрицы M. &lt;br /&gt;
&lt;br /&gt;
Матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; состоит из элементов &amp;lt;math&amp;gt;M = \|m_{ik}\|&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ik} = \begin{cases}&lt;br /&gt;
1, &amp;amp; \|u_k-c_i\|^2 \leqslant \|u_k-c_j\|^2 \;\; \text{for all } i \neq j; \;\; (i,j=1,2,\ldots,C; \; k = 1,2,\ldots,n)\\&lt;br /&gt;
0, &amp;amp; \text{otherwise}.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Шаг 3. Расчет объектной функции: &lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^C J_i = \sum\limits_{i=1}^C \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
На этом шаге происходит остановка и выход из цикла, если полученное значение ниже пороговой величины или полученное значение не сильно отличается от значений, полученных на предыдущих циклах.&lt;br /&gt;
&lt;br /&gt;
Шаг 4. Пересчет кластерных центров. &lt;br /&gt;
&lt;br /&gt;
Пересчет кластерных центров выполняется в соответствии со следующим уравнением: &lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где &amp;lt;math&amp;gt;|C_i|&amp;lt;/math&amp;gt; -- количество элементов в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом кластере.&lt;br /&gt;
&lt;br /&gt;
Шаг 5. Переход на шаг 2.&lt;br /&gt;
&lt;br /&gt;
Описание взято из &amp;lt;ref&amp;gt;[http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf Нейский И.М. Классификация и сравнение методов кластеризации // Интеллектуальные технологии и системы. Сборник учебно-методических работ и статей аспирантов и студентов. – М.: НОК «CLAIM», 2006. – Выпуск 8. – С. 130-142.]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма Hard C-Means можно составить из множественных (всего их &amp;lt;math&amp;gt;nC&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;: &amp;lt;math&amp;gt;\|u_k-c_i\|^2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Как записано и в описании ядра алгоритма, основную часть метода составляют множественные (&amp;lt;math&amp;gt;Cn&amp;lt;/math&amp;gt;) вычисления квадратов норм:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\|u_k-c_i\|^2&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;&lt;br /&gt;
J = \sum\limits_{i=1}^C J_i = \sum\limits_{i=1}^C \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Поэлементное суммирование векторов:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Итерационный блок алгоритма можно описать на языке Python следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python3&amp;quot;&amp;gt;&lt;br /&gt;
for i in range(n):&lt;br /&gt;
    idx_min = 0&lt;br /&gt;
    dist_min  = ((u[i] - c[0]) ** 2).sum()&lt;br /&gt;
&lt;br /&gt;
    for j in range(1, C):&lt;br /&gt;
        dist  = ((u[i] - c[j]) ** 2).sum()&lt;br /&gt;
        if dist &amp;lt; dist_min:&lt;br /&gt;
            idx_min = j&lt;br /&gt;
            dist_min = dist&lt;br /&gt;
&lt;br /&gt;
    M[i, idx_min] = 1&lt;br /&gt;
    c_next[idx_min] += u[i]&lt;br /&gt;
    c_next_cnt[idx_min] += 1&lt;br /&gt;
    J += dist_min&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
Предполагаем, что предельная точность алгоритма достигаема менее, чем за &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; итераций. Иначе использование алгоритма можно считать нерациональным. Также предположим, что размерность &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; и количество кластерных центров &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; существенно меньше &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Операция вычисления квадрата нормы разности векторов требует выполнения &amp;lt;math&amp;gt;m-1&amp;lt;/math&amp;gt; арифметических операций сложения, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; операций вычитания и &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
&lt;br /&gt;
Каждая итерация алгоритма требует выполнения:&lt;br /&gt;
* &amp;lt;math&amp;gt;nC&amp;lt;/math&amp;gt; операций вычисления квадрата нормы разности векторов;&lt;br /&gt;
* &amp;lt;math&amp;gt;nC&amp;lt;/math&amp;gt; операций сравнения квадрата нормы;&lt;br /&gt;
* &amp;lt;math&amp;gt;3n&amp;lt;/math&amp;gt; операций сложения;&lt;br /&gt;
&lt;br /&gt;
Таким образом, на каждой итерации имеем:&lt;br /&gt;
* &amp;lt;math&amp;gt;mnC&amp;lt;/math&amp;gt; операций умножения;&lt;br /&gt;
* &amp;lt;math&amp;gt;(2mC + 3)n&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания;&lt;br /&gt;
&lt;br /&gt;
В итоге имеем сложность последовательной реализации алгоритма &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Граф алгоритма состоит из 4 видов вершин:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первая&#039;&#039;&#039; группа вершин отмечена символом &#039;&#039;&#039;&#039;&#039;M&#039;&#039;&#039;&#039;&#039;. Ей соответствует вычисление минимального расстояния до кластерных центров, а также запись единицы в соответствующий столбец матрицы, обозначающей принадлежность кластерному центру:&lt;br /&gt;
* независимое вычисление расстояний от заданного элемента &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; до каждого из кластерных центров;&lt;br /&gt;
* последовательное сравнение полученных значений с целью отыскания максимума;&lt;br /&gt;
* операция записи 1 в соответствующий столбец матрицы принадлежности кластерным центрам;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вторая&#039;&#039;&#039; вершина отмечена символом &#039;&#039;&#039;&#039;&#039;J&#039;&#039;&#039;&#039;&#039;, на этом этапе происходит итоговый расчёт объектной функции.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Третья&#039;&#039;&#039; вершина помечена &#039;&#039;&#039;&#039;&#039;if&#039;&#039;&#039;&#039;&#039;, на этом этапе происходит проверка условия достижения требуемой точности.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Четвертая&#039;&#039;&#039; соответствует операции пересчёта кластерных центров, она отмечена как &#039;&#039;&#039;&#039;&#039;C&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
[[File:Cmeans.png|thumb|800px|center|Рисунок 1. Информационный граф алгоритма. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных, &#039;&#039;&#039;&#039;&#039;D&#039;&#039;&#039;&#039;&#039; — вычисление минимального расстояния до кластерных центров и проставление принадлежности соответствующему кластерному центру, &#039;&#039;&#039;&#039;&#039;J&#039;&#039;&#039;&#039;&#039; — вычисление объектной функции по результатам полученных вычислений, &#039;&#039;&#039;&#039;&#039;if&#039;&#039;&#039;&#039;&#039; — проверка условия достижения желаемой точности, &#039;&#039;&#039;&#039;&#039;C&#039;&#039;&#039;&#039;&#039; — пересчёт кластерных центров и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
Основной ресурс параллелизма алгоритма составляет итерационный блок. Эта последовательность итераций может быть выполнена для каждого входного вектора &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; независимо. Однако, в конце выполнения каждого итерационного блока имеют место последовательные вычисления - сложение значений объектной функции, полученных независимо на каждом процессоре, а также перерасчет кластерных центров.&lt;br /&gt;
&lt;br /&gt;
Высота [[глоссарий#Ярусно-параллельная форма графа алгоритма|ЯПФ]] оценивается как &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt; (при условии, что число итераций существенно меньше объёма выборки &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;). Ширина [[глоссарий#Ярусно-параллельная форма графа алгоритма|ЯПФ]] равна &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Необходимо учитывать, что при небольшом объеме входной выборки, параллельная реализация алгоритма может лишь понизить производительность. В первую очередь это связано с пересылкой данных для вычисления итоговых значений объектной функции и кластерных центров.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; матрица &amp;lt;math&amp;gt;U\in \mathbb{R}^{n\times m}&amp;lt;/math&amp;gt;, представляющая собой набор векторов &amp;lt;math&amp;gt;\{u_i\}_{i=1}^{n}, u_i \in \mathbb{R}^m&amp;lt;/math&amp;gt;; количество кластеров &amp;lt;math&amp;gt;C \in \mathbb{N}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;nm+1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; набор векторов - кластерных центров &amp;lt;math&amp;gt;\{c_i\}_{i=1}^{C}, c_i \in \mathbb{R}^m&amp;lt;/math&amp;gt;; матрица &amp;lt;math&amp;gt;M\in \mathbb{N}^{n\times C}&amp;lt;/math&amp;gt; c информацией о разбиении объектов на кластера. Элемент &amp;lt;math&amp;gt;m_{ij}=1&amp;lt;/math&amp;gt;, если &amp;lt;math&amp;gt;u_j \in C_i&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; содержит все объекты &amp;lt;math&amp;gt;u&amp;lt;/math&amp;gt;, принадлежащие кластеру &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;. Остальные элементы &amp;lt;math&amp;gt;m_{ij}=0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;(n+m)C&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
Достоинства:&lt;br /&gt;
&lt;br /&gt;
* лёгкость реализации;&lt;br /&gt;
* вычислительная простота;&lt;br /&gt;
* может служить для кластеризации больших наборов числовых данных;&lt;br /&gt;
&lt;br /&gt;
Недостатки:&lt;br /&gt;
&lt;br /&gt;
* задание количества кластеров;&lt;br /&gt;
* отсутствие гарантии в нахождении оптимального решения;&lt;br /&gt;
&lt;br /&gt;
Соотношение последовательной и параллельной сложности алгоритма: линейное.&lt;br /&gt;
&lt;br /&gt;
Вычислительная мощность алгоритма, как отношение числа операций к суммарному объему входных и выходных данных равна константе.&lt;br /&gt;
&lt;br /&gt;
Алгоритм является недетерминированным, т.к. он является итерационным с выходом по точности, а также использует датчик случайных чисел для инициализации кластерных центров.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===	&lt;br /&gt;
=== Локальность данных и вычислений ===	&lt;br /&gt;
==== Локальность реализации алгоритма ====	&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====	&lt;br /&gt;
===== Количественная оценка локальности =====	&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
Проведём исследование масштабируемости параллельной реализации строгого алгоритма C средних согласно [[Scalability methodology|методике]].&lt;br /&gt;
&lt;br /&gt;
Исследование проводилось на 1U сервере со &#039;&#039;&#039;следующими характеристиками&#039;&#039;&#039;:&lt;br /&gt;
*	2 x Intel® Xeon® Processor E5-2697 v2;&lt;br /&gt;
*	128GB RAM;&lt;br /&gt;
&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
Сборка осуществлялась со следующими параметрами:&lt;br /&gt;
&lt;br /&gt;
*	GCC-4.8.4;&lt;br /&gt;
*	OpenMP-3.1;&lt;br /&gt;
*	аргументы компилятора: -std=c++11 -O3;&lt;br /&gt;
&lt;br /&gt;
Набор и границы значений изменяемых [[Глоссарий#Параметры запуска|параметров запуска]] реализации алгоритма: &lt;br /&gt;
&lt;br /&gt;
*	число процессоров [1 : 48] с шагом 1;&lt;br /&gt;
*	размерность пространства [3 : 50] c шагом 3;&lt;br /&gt;
*	число векторов 100 000 000;&lt;br /&gt;
*	число кластерных центров 30;&lt;br /&gt;
&lt;br /&gt;
В результате проведённых экспериментов был получен следующий диапазон [[Глоссарий#Эффективность реализации|эффективности реализации]] алгоритма (отношение реальной производительности программы к пиковым показателям работы вычислительной системы):&lt;br /&gt;
&lt;br /&gt;
*	минимальная эффективность реализации 0.014;&lt;br /&gt;
*	максимальная эффективность реализации 0.9;&lt;br /&gt;
&lt;br /&gt;
На следующих рисунках приведены графики [[Глоссарий#Производительность|производительности]] и эффективности выбранной реализации HCM в зависимости от изменяемых параметров запуска.&lt;br /&gt;
&lt;br /&gt;
[[file:GFLOPS_AA.png|thumb|center|700px|Рисунок 2. Параллельная реализация алгоритма. Изменение производительности в зависимости от числа процессоров и размерности векторов.]]&lt;br /&gt;
[[file:EFFICIENCY.png|thumb|center|700px|Рисунок 3. Параллельная реализация алгоритма. Изменение эффективности в зависимости от числа процессоров и размерности векторов.]]&lt;br /&gt;
&lt;br /&gt;
==== Реализация на языке C++ ====&lt;br /&gt;
[http://pastebin.com/31UkHgcW Исследованная параллельная реализация на языке C++]&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
* [http://projects.jasmeet.me/2013/03/HardCMeans.html Последовательная реализация алгоритма на MatLab]&lt;br /&gt;
* [https://github.com/artpar/Hard-Clustering-implementation Последовательная реализация алгоритма на С++]&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Coctic</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:%D0%9A%D0%B0%D0%BB%D0%B5%D0%B4%D0%B0_%D0%90%D0%BB%D0%B5%D0%BA%D1%81%D0%B0%D0%BD%D0%B4%D1%80&amp;diff=18998</id>
		<title>Обсуждение участника:Каледа Александр</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:%D0%9A%D0%B0%D0%BB%D0%B5%D0%B4%D0%B0_%D0%90%D0%BB%D0%B5%D0%BA%D1%81%D0%B0%D0%BD%D0%B4%D1%80&amp;diff=18998"/>
		<updated>2016-11-23T10:16:50Z</updated>

		<summary type="html">&lt;p&gt;Coctic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Статья [[Участник:Каледа Александр/Строгий алгоритм С средних (Hard C-Means)]] =&lt;br /&gt;
* Не указан вклад каждого автора [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:08, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:42, 2 ноября 2016 (MSK)&lt;br /&gt;
* Стоит добавить ссылку на оригинальную публикацию, в которой был впервые предложен алгоритм. [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:08, 25 октября 2016 (MSK)&lt;br /&gt;
** Не исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:42, 2 ноября 2016 (MSK)&lt;br /&gt;
* Значительная часть п. 1.2  совпадает с тем же пунктом из [[Строгий алгоритм С средних (Hard C-Means, HCM)]]&lt;br /&gt;
** Замечание снимается [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:42, 2 ноября 2016 (MSK)&lt;br /&gt;
* Пункты раздела 2 не соответствуют шаблону. П. 2.1 должен быть 2.4, п. 2.2 должен быть 2.7, остальные пункты пропущены [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:08, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:42, 2 ноября 2016 (MSK)&lt;br /&gt;
* В списке литературы отсутствуют выходные данные публикаций, кроме названия и автора. По приведенным данным определить конкретную публикацию не представляется возможным. [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:08, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:42, 2 ноября 2016 (MSK)&lt;br /&gt;
* Список литературы совпадает со списком из [[Строгий алгоритм С средних (Hard C-Means, HCM)]] [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:08, 25 октября 2016 (MSK)&lt;br /&gt;
** Замечание снимается [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:42, 2 ноября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
------------&lt;br /&gt;
* Стоит добавить ссылку на оригинальную публикацию, в которой был впервые предложен алгоритм [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:42, 2 ноября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:16, 23 ноября 2016 (MSK)&lt;br /&gt;
* п. 2.4.1 пустой. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:35, 17 ноября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:16, 23 ноября 2016 (MSK)&lt;br /&gt;
* п. 2.4.2. Отсутствует ссылка на текст исследуемой программы и аппаратную платформу, на которой проводилось тестирование. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:35, 17 ноября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:16, 23 ноября 2016 (MSK)&lt;br /&gt;
* Рис. 3. В подписи к рисунку не указано, график зависимости эффективности какого типа приведен. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:35, 17 ноября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:16, 23 ноября 2016 (MSK)&lt;/div&gt;</summary>
		<author><name>Coctic</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:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%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_(Hard_C-Means,_HCM)&amp;diff=18997</id>
		<title>Участник:Светлана Лукьяненко/Строгий алгоритм С средних (Hard C-Means, HCM)</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:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%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_(Hard_C-Means,_HCM)&amp;diff=18997"/>
		<updated>2016-11-23T10:15:05Z</updated>

		<summary type="html">&lt;p&gt;Coctic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{assignment|{{REVISIONUSER}}}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Строгий алгоритм С средних (Hard C-Means,HCM)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;nN+1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;C(N+n)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Авторы описания: [[Участник:Светлана_Лукьяненко|Лукьяненко Светлана]](1.1, 1.3, 1.4, 1.8, 1.10, 2.4, 2.7), [[Участник:Юрий_Комаров|Комаров Юрий]](1.2, 1.5, 1.6, 1.7, 1.8, 1.9, 2.4)&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Строгий алгоритм C средних&#039;&#039;&#039; (&#039;&#039;&#039;&#039;&#039;Hard C-Means&#039;&#039;&#039;&#039;&#039;; &#039;&#039;Jang, Sun and Mizutani, 1997&#039;&#039;&amp;lt;ref&amp;gt;Jang, J.-S. R., Sun, C.-T. and Mizutani, E. (1997). Neuro-Fuzzy and Soft Computing, number&lt;br /&gt;
isbn 0-13-261066-3 in Matlab Curriculum Series, Prentice Hall, Upper Saddle River, NJ, USA.&amp;lt;/ref&amp;gt;) позволяет распределить большие наборы числовых данных по кластерам в многомерном пространстве&amp;lt;ref&amp;gt;Jan Jantzen (1998). [http://faculty.petra.ac.id/resmana/private/fuzzy/nfmod.pdf Neurofuzzy Modelling.]&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;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
==== Входные и выходные данные ====&lt;br /&gt;
На вход подаётся набор векторов &amp;lt;math&amp;gt;\{u_k\}_{k=1}^{N}&amp;lt;/math&amp;gt; пространства &amp;lt;math&amp;gt;\mathbb{R}^n&amp;lt;/math&amp;gt; и количество кластеров &amp;lt;math&amp;gt;C&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;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ij} = \begin{cases}&lt;br /&gt;
1, &amp;amp; u_j \in C_i, \\&lt;br /&gt;
0, &amp;amp; \text{otherwise},&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; подразумевается &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый построенный кластер, и набор &amp;lt;math&amp;gt;\{c_i\}_{i=1}^{C}&amp;lt;/math&amp;gt; центров этих кластеров.&lt;br /&gt;
&lt;br /&gt;
==== Описание алгоритма ====&lt;br /&gt;
Алгоритм состоит из 5 последовательных шагов.&amp;lt;ref&amp;gt;Нейский И. М. [http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf Классификация и сравнение методов кластеризации.] // Интеллектуальные технологии и системы. Сборник учебно-методических работ и статей аспирантов и студентов. – М.: НОК «CLAIM», 2006. – Выпуск 8. – С. 130-142.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 1&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация кластерных центров&#039;&#039;&#039; &amp;lt;math&amp;gt;c_i \, (i=1,2,\ldots,C)&amp;lt;/math&amp;gt; может происходить за счёт случайного выбора необходимого числа точек из входного набора либо путём явного указания.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 2&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вычисление рядовой матрицы&#039;&#039;&#039; &amp;lt;math&amp;gt;M = \|m_{ik}\|&amp;lt;/math&amp;gt;, элементы которой задаются следующими выражениями (&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; — количество элементов во входном наборе данных):&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ik} = \begin{cases}&lt;br /&gt;
1, &amp;amp; \|u_k-c_i\|^2 \leqslant \|u_k-c_j\|^2 \;\; \text{for all } i \neq j; \;\; (i,j=1,2,\ldots,C; \; k = 1,2,\ldots,N)\\&lt;br /&gt;
0, &amp;amp; \text{otherwise}.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;!-- При этом, как легко видеть, матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; обладает следующими свойствами:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\sum\limits_{i=1}^C m_{ij} = 1, \;\; \sum\limits_{i=1}^C\sum\limits_{j=1}^K m_{ij} = K.&lt;br /&gt;
&amp;lt;/math&amp;gt; --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Будем говорить, что &amp;lt;math&amp;gt;u_k \in C_i&amp;lt;/math&amp;gt;, если &amp;lt;math&amp;gt;m_{ik} = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 3&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Расчёт объектной функции:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^C J_i = \sum\limits_{i=1}^C \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right)&lt;br /&gt;
.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На этом шаге происходит &#039;&#039;&#039;&amp;lt;u&amp;gt;остановка и выход из цикла&amp;lt;/u&amp;gt;&#039;&#039;&#039;, если полученное значение ниже пороговой величины &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; или полученное значение не сильно отличается от значений, полученных на предыдущих циклах.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 4&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Пересчёт кластерных центров&#039;&#039;&#039; выполняется в соответствии со следующим уравнением:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;|C_i|&amp;lt;/math&amp;gt; подразумевается количество элементов в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом кластере.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 5&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Переход по циклу&#039;&#039;&#039; на шаг 2.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма составляют вычисления квадратов нормы расстояния от каждого из векторов исходной выборки до промежуточных кластерных центров &amp;lt;math&amp;gt;\|u_k-c_i\|^2&amp;lt;/math&amp;gt;. На каждой итерации алгоритма происходит расчёт &amp;lt;math&amp;gt;CN&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;&lt;br /&gt;
d_{ki} = \|u_k-c_i\|^2&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также на шаге вычисления объектной функции производится множественное суммирование полученных расстояний:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^C J_i = \sum\limits_{i=1}^C \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right),&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
а на шаге расчета кластерных центров происходит суммирование векторов:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Реализация последовательного алгоритма состоит в итеративном повторении блока, описанного далее в форме псевдокода, до тех пор, пока не будет достигнута желаемая точность.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;&lt;br /&gt;
J = 0;&lt;br /&gt;
M = zeros(N,C);&lt;br /&gt;
for i = 1 to N //go through every element&lt;br /&gt;
   d_min = MAXINT;&lt;br /&gt;
   j_min = 1;&lt;br /&gt;
   for j = 1 to C //deside which claster does element belong to&lt;br /&gt;
      d_ij  = sq_norm(u[i] - c[j]);&lt;br /&gt;
      if d_ij &amp;lt; d_min&lt;br /&gt;
         d_min = d_ij;&lt;br /&gt;
         j_min = j;&lt;br /&gt;
   //generation of output data&lt;br /&gt;
   J += d_min; &lt;br /&gt;
   M[i,j_min] = 1;&lt;br /&gt;
   c_new[j] += u[i];&lt;br /&gt;
   c_newCount[k]++;&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;NC&amp;lt;/math&amp;gt; операций вычисления квадрата нормы разности элементов;&lt;br /&gt;
* &amp;lt;math&amp;gt;NC&amp;lt;/math&amp;gt; операций сравнения (вычитаний);&lt;br /&gt;
* &amp;lt;math&amp;gt;3N&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
&lt;br /&gt;
Каждая операция вычисления нормы разности векторов предполагает выполнение &amp;lt;math&amp;gt;2n-1&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания и &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; операций возведения в квадрат (умножений), поэтому получаем для каждой итерации:&lt;br /&gt;
* &amp;lt;math&amp;gt;(2nC + 3)N&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания;&lt;br /&gt;
* &amp;lt;math&amp;gt;nNC&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
&lt;br /&gt;
Ожидая, что предельная точность будет достигнута менее, чем за &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; итераций (в противном случае применение алгоритма можно считать нецелесообразным), получаем итоговую сложность последовательной реализации алгоритма &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt; (в предположении, что &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; существенно меньше &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Приведём аналитическое и графическое описание графа алгоритма.&lt;br /&gt;
&lt;br /&gt;
Граф алгоритма состоит из 5 различных видов вершин.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первая&#039;&#039;&#039; группа вершин отмечена символом &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039;, ей соответствует вычисление минимального расстояния до кластерных центров, включающее в себя следующую последовательность действий:&lt;br /&gt;
* независимое вычисление расстояний от заданного элемента &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; до каждого из кластерных центров;&lt;br /&gt;
* последовательное сравнение полученных значений с целью отыскания минимума;&lt;br /&gt;
* передача найденного минимального расстояния и соответствующего ему индекса кластера.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вторая&#039;&#039;&#039; группа вершин отмечена символом &#039;&#039;&#039;&#039;&#039;M&#039;&#039;&#039;&#039;&#039;, ей соответствует операция записи единички в столбец, отвечающий текущей ветке графа, в позицию, полученную на предыдущем шаге и соответствующую ближайшему кластерному центру.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Третья&#039;&#039;&#039; вершина отмечена символом &#039;&#039;&#039;&#039;&#039;J&#039;&#039;&#039;&#039;&#039;, подразумевается, что на этом этапе происходит расчёт объектной функции.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Четвертая&#039;&#039;&#039; вершина обозначена треугольным маркером и помечена &#039;&#039;&#039;&#039;&#039;if&#039;&#039;&#039;&#039;&#039;, на этом этапе происходит проверка условия достижения необходимой точности (условия остановки итерационного процесса).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Пятая&#039;&#039;&#039; соответствует операции пересчёта кластерных центров, она отмечена как &#039;&#039;&#039;&#039;&#039;{c}&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Все эти виды вершин визуально выделены в одну большую группу, поскольку все вместе они составляют одну полную итерацию алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:HardCMeans1.png|thumb|800px|center|Рисунок 1. Информационный граф алгоритма. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (&amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; стартовых значений кластерных центров и 1 значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; на каждую вершину графа), &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039; — вычисление минимального расстояния до кластерных центров (подробнее см. рисунок 2), &#039;&#039;&#039;&#039;&#039;M&#039;&#039;&#039;&#039;&#039; — запись единички в соответствующий столбец матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, &#039;&#039;&#039;&#039;&#039;J&#039;&#039;&#039;&#039;&#039; — вычисление объектной функции по результатам полученных вычислений, &#039;&#039;&#039;&#039;&#039;if&#039;&#039;&#039;&#039;&#039; — проверка условия достижения заданной точности, &#039;&#039;&#039;&#039;&#039;{c}&#039;&#039;&#039;&#039;&#039; — пересчёт кластерных центров и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; значений полученных кластерных центров).]]&lt;br /&gt;
[[File:HardCMeans2.PNG|thumb|400px|center|Рисунок 2. Подробное описание работы блока  &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039;. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (по 1 значению центра кластера на каждую из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; соответствующих вершин графа и значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;, единое для этого &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039;-блока), &#039;&#039;&#039;&#039;&#039;d1,...,dC&#039;&#039;&#039;&#039;&#039; — прямое вычисление  расстояния до кластерных центров, &#039;&#039;&#039;&#039;&#039;min&#039;&#039;&#039;&#039;&#039; — вычисление минимума двух чисел (с сохранением соответствующего минимуму кластерного индекса) и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (индекс кластерного центра, расположенного ближе всего к точке &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;, и соответствующее расстояние).]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
Для выполнения одной итерации алгоритма C средних необходимо выполнить параллельно ряд вычислений для каждого из &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; элементов:&lt;br /&gt;
&lt;br /&gt;
# Вычисление &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; расстояний между элементом и кластерными центрами.&lt;br /&gt;
# Выполнение &amp;lt;math&amp;gt;(C - 1)&amp;lt;/math&amp;gt; сравнений для определения минимального.&lt;br /&gt;
# Определение значений соответствующего рассматриваемому элементу &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; столбца матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Эта последовательность операций может быть выполнена для каждого элемента &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; входной выборки независимо и поэтому составляет основной ресурс параллелизма алгоритма.&lt;br /&gt;
&lt;br /&gt;
При этом, как можно видеть из информационного графа алгоритма, часть вычислений проводится в последовательном режиме, например, расчёт значения объектной функции &amp;lt;math&amp;gt;J&amp;lt;/math&amp;gt;. Аналогичная ситуация имеет место и с пересчётом кластерных центров — разделив эту операцию на &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; независимых процессов, мы потеряем в производительности за счёт увеличения накладных расходов, связанных с пересылкой данных и координацией вычислений.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что при малом объёме выборки и размерности системы попытка использования параллельной реализации алгоритма приведёт к понижению производительности, поскольку проведение последовательных расчётов потребует меньше времени, нежели пересылка данных (хотя бы матриц размера &amp;lt;math&amp;gt;nC&amp;lt;/math&amp;gt;, определяющих кластерные центры).&lt;br /&gt;
&lt;br /&gt;
При этом, как легко видеть, ширина [[глоссарий#Ярусно-параллельная форма графа алгоритма|ЯПФ]] составляет &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt; (если быть точнее, просто &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;). Высота ЯПФ для строгого алгоритма C средних оценивается как &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt; (предполагаем, что число итераций существенно меньше объёма выборки &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; &lt;br /&gt;
*&amp;lt;math&amp;gt;\{u_k\}_{k=1}^{N} \subset \mathbb{R}^n&amp;lt;/math&amp;gt; — исходный набор векторов;&lt;br /&gt;
*&amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; — количество кластеров (&amp;lt;math&amp;gt;2 \leqslant C \leqslant N&amp;lt;/math&amp;gt;);&lt;br /&gt;
* &#039;&#039;(опционально)&#039;&#039; &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; — пороговая точность работы алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;nN+1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
*&amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; — рядовая матрица из пространства &amp;lt;math&amp;gt;\mathbb{R}^{C \times N}&amp;lt;/math&amp;gt;.&lt;br /&gt;
*&amp;lt;math&amp;gt;\{c_k\}_{k=1}^{C}&amp;lt;/math&amp;gt; — набор построенных кластерных центров.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;C(N+n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Назначение:&#039;&#039;&#039; кластеризация больших наборов числовых данных.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Достоинства:&#039;&#039;&#039;&lt;br /&gt;
* лёгкость реализации;&lt;br /&gt;
* вычислительная простота.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Недостатки:&#039;&#039;&#039;&lt;br /&gt;
* нет гарантии, что итерационный процесс сойдётся к оптимальному решению;&lt;br /&gt;
* производительность существенно зависит от выбора начальных кластерных центров.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
Исследуем масштабируемость параллельной реализации строгого алгоритма C средних, соответствующей последовательной реализации, описанной в [[#Схема реализации последовательного алгоритма|п1.5]]. Для проведения расчётов использовались ресурсы вычислительного комплекса [http://hpc.cmc.msu.ru/bgp IBM Blue Gene/P] и [https://github.com/ykomarov94/AlgoWiki собственная реализация алгоритма].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Основные характеристики реализации алгоритма и запуска программы:&amp;lt;/u&amp;gt;&lt;br /&gt;
* программа написана на языке C с использованием [http://hpc.cmc.msu.ru/bgp/development/parallel библиотеки MPI];&lt;br /&gt;
* сборка программы произведена с использованием компилятора [http://hpc.cmc.msu.ru/bgp/development/compilers IBM XL C Advanced Edition for Blue Gene/P V9.0] версии 9.0.0.0005;&lt;br /&gt;
* при компиляции не использовались дополнительные опции;&lt;br /&gt;
* при тестировании использовались псевдослучайные наборы векторов заданной размерности;&lt;br /&gt;
* для каждой конфигурации проводилась серия экспериментов, после чего для получения конечных результатов производительности проводилось усреднение.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Набор и границы значений изменяемых параметров запуска реализации алгоритма:&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* число процессоров &amp;lt;math&amp;gt;[16 : 256]&amp;lt;/math&amp;gt; с шагом по степеням двойки;&lt;br /&gt;
* объём выборки &amp;lt;math&amp;gt;[10^3:10^7]&amp;lt;/math&amp;gt;  с шагом по степеням десятки;&lt;br /&gt;
* размерность системы &amp;lt;math&amp;gt;n=10&amp;lt;/math&amp;gt;;&lt;br /&gt;
* количество кластеров &amp;lt;math&amp;gt;C = 11&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве изменяемого параметра для построения графика был выбран объём выборки &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, поскольку варьирование прочих параметров существенно хуже отражает возможности применения технологии параллельных вычислений. Это связано с тем, что при малом количестве векторов время, затраченное на пересылку данных, сравнимо со временем, затрачиваемым непосредственно на расчёты; это хорошо видно на графике: при объёмах выборки, составляющих &amp;lt;math&amp;gt;10^3&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;10^4&amp;lt;/math&amp;gt; векторов, использование большего числа процессоров не приводит к приросту производительности (наоборот, производительность падает) ввиду высоких накладных расходов.&lt;br /&gt;
&lt;br /&gt;
[[file:HardCMeansPerfomance.png|thumb|center|700px|Рис.3 Реализация строгого алгоритма C средних. График производительности (GFLOPS) в зависимости от числа процессоров и объёма выборки.]]&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
1)  [https://github.com/artpar/Hard-Clustering-implementation Последовательная реализация на С++ ]&lt;br /&gt;
&lt;br /&gt;
2) [http://projects.jasmeet.me/2013/03/HardCMeans.html Последовательная реализация на MatLab ]&lt;br /&gt;
&lt;br /&gt;
На момент публикации параллельных реализаций в свободном доступе обнаружено не было.&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Coctic</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE&amp;diff=18996</id>
		<title>Обсуждение участника:Светлана Лукьяненко</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE&amp;diff=18996"/>
		<updated>2016-11-23T10:14:36Z</updated>

		<summary type="html">&lt;p&gt;Coctic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Статья [[Участник:Светлана Лукьяненко/Строгий алгоритм С средних (Hard C-Means, HCM)]] =&lt;br /&gt;
* Не указан вклад каждого автора [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:57, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:05, 31 октября 2016 (MSK)&lt;br /&gt;
* Значительная часть п. 1.2  совпадает с тем же пунктом из [[Участник:Каледа Александр/Строгий алгоритм С средних (Hard C-Means)]] [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:05, 25 октября 2016 (MSK)&lt;br /&gt;
** Замечание снимается [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:05, 31 октября 2016 (MSK)&lt;br /&gt;
* В списке литературы отсутствуют выходные данные публикаций, кроме названия и автора. По приведенным данным определить конкретную публикацию не представляется возможным. Стоит добавить ссылку на оригинальную публикацию с описанием алгоритма, упомянутую в начале п.1.1 [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:57, 25 октября 2016 (MSK)&lt;br /&gt;
** Не исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:05, 31 октября 2016 (MSK)&lt;br /&gt;
* Список литературы совпадает со списком из [[Участник:Каледа Александр/Строгий алгоритм С средних (Hard C-Means)]] [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:01, 25 октября 2016 (MSK)&lt;br /&gt;
** Замечание снимается [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:05, 31 октября 2016 (MSK)&lt;br /&gt;
----------------------&lt;br /&gt;
* Комментарий от [[Участник:Юрий Комаров|Комарова Юрия]]: Сравните, пожалуйста, нашу историю работы над статьёй с историей работы над статьёй наших коллег: Каледы и его товарища. Сделав это, Вы обнаружите, что мы начали работать сразу же после выдачи задания, практически одними из первых и гораздо раньше указанных ребят, и неоднократно правили каждый из пунктов, доводя их до лучшей кондиции. За то, что пункт 1.2, как, впрочем, и другие пункты, и список литературы были составлены нами лично в процессе длительной совместной работы со [[Участник:Светлана Лукьяненко|Светланой]], отвечаю головой. Надеюсь, вопрос о плагиате больше не возникнет. В такой ситуации исправлять что-то должны явно не мы. С уважением, Комаров Юрий.&lt;br /&gt;
** В мои задачи не входить обвинять кого-то в плагиате, проводить расследования, кто у кого списал, или выяснять, кто прав, а кто нет. Меня попросили проверить статью, обращая внимание на пересечения с другими на ту же тему. В двух статьях есть общая часть, это пошло в замечания к обеим статьям. Пересечение уйдет - замечание снимется. Кто исправит текст - мне все равно. Когда в статье появится метка, что ее можно снова проверять - я сравню тексты снова. Пока текст совпадает - замечание с моей стороны остается. Есть А.С. Антонов, если он сочтет, что это замечание можно проигнорировать (в одной статье или в обеих) - он продвинет статью дальше. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 18:31, 28 октября 2016 (MSK)&lt;br /&gt;
** Если говорить о, скажем мягко, некорректном заимствовании, то ваш п 1.2 есть воспроизведение фрагмента из работы Нейского с небольшими добавлениями. У вас имеется разрешение автора на такое воспроизведение? Так что не стоит так сразу головой-то... [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 18:31, 28 октября 2016 (MSK)&lt;br /&gt;
** В общем, не стоит отвечать в таком тоне. Я могу понять возмущение, но писать надо корректнее. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 18:31, 28 октября 2016 (MSK)&lt;br /&gt;
* Вклад авторов указан, в источниках приведены ссылки. Исправлять часть статьи, которую у нас украли наши коллеги (дата создания их страницы 15 октября), должны не мы, а указанные личности. К сожалению, заставить их это сделать мы не можем, полагаю, регулирование этого вопроса нам разумнее доверить проверяющим.&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
* В списке литературы отсутствуют выходные данные публикаций, кроме названия и автора. По приведенным данным определить конкретную публикацию не представляется возможным. Стоит добавить ссылку на оригинальную публикацию с описанием алгоритма, упомянутую в начале п.1.1  [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:05, 31 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:06, 3 ноября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
* п. 2.4. Не приведена ссылка на текст анализируемой программы. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:38, 17 ноября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:28, 22 ноября 2016 (MSK)&lt;br /&gt;
* Необходимо указать характеристики программно-аппаратной платформы (какой компилятор, с какими опциями использовался, какие версии библиотек, на каких узлах проводился запуск и т.д.) [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:28, 22 ноября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:14, 23 ноября 2016 (MSK)&lt;br /&gt;
* В подписи к рис. 3 указано, что это &#039;&#039;График производительности ... от числа параллельных процессов&#039;&#039;, а подписи к оси указано, что по ней отложено число процессоров (Processors). Какой вариант правильный? [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:28, 22 ноября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:14, 23 ноября 2016 (MSK)&lt;/div&gt;</summary>
		<author><name>Coctic</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:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%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_(Hard_C-Means,_HCM)&amp;diff=18951</id>
		<title>Участник:Светлана Лукьяненко/Строгий алгоритм С средних (Hard C-Means, HCM)</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:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%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_(Hard_C-Means,_HCM)&amp;diff=18951"/>
		<updated>2016-11-22T12:28:45Z</updated>

		<summary type="html">&lt;p&gt;Coctic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Строгий алгоритм С средних (Hard C-Means,HCM)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;nN+1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;C(N+n)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Авторы описания: [[Участник:Светлана_Лукьяненко|Лукьяненко Светлана]](1.1, 1.3, 1.4, 1.8, 1.10, 2.4, 2.7), [[Участник:Юрий_Комаров|Комаров Юрий]](1.2, 1.5, 1.6, 1.7, 1.8, 1.9, 2.4)&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Строгий алгоритм C средних&#039;&#039;&#039; (&#039;&#039;&#039;&#039;&#039;Hard C-Means&#039;&#039;&#039;&#039;&#039;; &#039;&#039;Jang, Sun and Mizutani, 1997&#039;&#039;&amp;lt;ref&amp;gt;Jang, J.-S. R., Sun, C.-T. and Mizutani, E. (1997). Neuro-Fuzzy and Soft Computing, number&lt;br /&gt;
isbn 0-13-261066-3 in Matlab Curriculum Series, Prentice Hall, Upper Saddle River, NJ, USA.&amp;lt;/ref&amp;gt;) позволяет распределить большие наборы числовых данных по кластерам в многомерном пространстве&amp;lt;ref&amp;gt;Jan Jantzen (1998). [http://faculty.petra.ac.id/resmana/private/fuzzy/nfmod.pdf Neurofuzzy Modelling.]&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;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
==== Входные и выходные данные ====&lt;br /&gt;
На вход подаётся набор векторов &amp;lt;math&amp;gt;\{u_k\}_{k=1}^{N}&amp;lt;/math&amp;gt; пространства &amp;lt;math&amp;gt;\mathbb{R}^n&amp;lt;/math&amp;gt; и количество кластеров &amp;lt;math&amp;gt;C&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;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ij} = \begin{cases}&lt;br /&gt;
1, &amp;amp; u_j \in C_i, \\&lt;br /&gt;
0, &amp;amp; \text{otherwise},&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; подразумевается &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый построенный кластер, и набор &amp;lt;math&amp;gt;\{c_i\}_{i=1}^{C}&amp;lt;/math&amp;gt; центров этих кластеров.&lt;br /&gt;
&lt;br /&gt;
==== Описание алгоритма ====&lt;br /&gt;
Алгоритм состоит из 5 последовательных шагов.&amp;lt;ref&amp;gt;Нейский И. М. [http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf Классификация и сравнение методов кластеризации.] // Интеллектуальные технологии и системы. Сборник учебно-методических работ и статей аспирантов и студентов. – М.: НОК «CLAIM», 2006. – Выпуск 8. – С. 130-142.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 1&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация кластерных центров&#039;&#039;&#039; &amp;lt;math&amp;gt;c_i \, (i=1,2,\ldots,C)&amp;lt;/math&amp;gt; может происходить за счёт случайного выбора необходимого числа точек из входного набора либо путём явного указания.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 2&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вычисление рядовой матрицы&#039;&#039;&#039; &amp;lt;math&amp;gt;M = \|m_{ik}\|&amp;lt;/math&amp;gt;, элементы которой задаются следующими выражениями (&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; — количество элементов во входном наборе данных):&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ik} = \begin{cases}&lt;br /&gt;
1, &amp;amp; \|u_k-c_i\|^2 \leqslant \|u_k-c_j\|^2 \;\; \text{for all } i \neq j; \;\; (i,j=1,2,\ldots,C; \; k = 1,2,\ldots,N)\\&lt;br /&gt;
0, &amp;amp; \text{otherwise}.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;!-- При этом, как легко видеть, матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; обладает следующими свойствами:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\sum\limits_{i=1}^C m_{ij} = 1, \;\; \sum\limits_{i=1}^C\sum\limits_{j=1}^K m_{ij} = K.&lt;br /&gt;
&amp;lt;/math&amp;gt; --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Будем говорить, что &amp;lt;math&amp;gt;u_k \in C_i&amp;lt;/math&amp;gt;, если &amp;lt;math&amp;gt;m_{ik} = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 3&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Расчёт объектной функции:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^C J_i = \sum\limits_{i=1}^C \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right)&lt;br /&gt;
.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На этом шаге происходит &#039;&#039;&#039;&amp;lt;u&amp;gt;остановка и выход из цикла&amp;lt;/u&amp;gt;&#039;&#039;&#039;, если полученное значение ниже пороговой величины &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; или полученное значение не сильно отличается от значений, полученных на предыдущих циклах.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 4&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Пересчёт кластерных центров&#039;&#039;&#039; выполняется в соответствии со следующим уравнением:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;|C_i|&amp;lt;/math&amp;gt; подразумевается количество элементов в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом кластере.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 5&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Переход по циклу&#039;&#039;&#039; на шаг 2.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма составляют вычисления квадратов нормы расстояния от каждого из векторов исходной выборки до промежуточных кластерных центров &amp;lt;math&amp;gt;\|u_k-c_i\|^2&amp;lt;/math&amp;gt;. На каждой итерации алгоритма происходит расчёт &amp;lt;math&amp;gt;CN&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;&lt;br /&gt;
d_{ki} = \|u_k-c_i\|^2&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также на шаге вычисления объектной функции производится множественное суммирование полученных расстояний:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^C J_i = \sum\limits_{i=1}^C \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right),&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
а на шаге расчета кластерных центров происходит суммирование векторов:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Реализация последовательного алгоритма состоит в итеративном повторении блока, описанного далее в форме псевдокода, до тех пор, пока не будет достигнута желаемая точность.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;&lt;br /&gt;
J = 0;&lt;br /&gt;
M = zeros(N,C);&lt;br /&gt;
for i = 1 to N //go through every element&lt;br /&gt;
   d_min = MAXINT;&lt;br /&gt;
   j_min = 1;&lt;br /&gt;
   for j = 1 to C //deside which claster does element belong to&lt;br /&gt;
      d_ij  = sq_norm(u[i] - c[j]);&lt;br /&gt;
      if d_ij &amp;lt; d_min&lt;br /&gt;
         d_min = d_ij;&lt;br /&gt;
         j_min = j;&lt;br /&gt;
   //generation of output data&lt;br /&gt;
   J += d_min; &lt;br /&gt;
   M[i,j_min] = 1;&lt;br /&gt;
   c_new[j] += u[i];&lt;br /&gt;
   c_newCount[k]++;&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;NC&amp;lt;/math&amp;gt; операций вычисления квадрата нормы разности элементов;&lt;br /&gt;
* &amp;lt;math&amp;gt;NC&amp;lt;/math&amp;gt; операций сравнения (вычитаний);&lt;br /&gt;
* &amp;lt;math&amp;gt;3N&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
&lt;br /&gt;
Каждая операция вычисления нормы разности векторов предполагает выполнение &amp;lt;math&amp;gt;2n-1&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания и &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; операций возведения в квадрат (умножений), поэтому получаем для каждой итерации:&lt;br /&gt;
* &amp;lt;math&amp;gt;(2nC + 3)N&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания;&lt;br /&gt;
* &amp;lt;math&amp;gt;nNC&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
&lt;br /&gt;
Ожидая, что предельная точность будет достигнута менее, чем за &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; итераций (в противном случае применение алгоритма можно считать нецелесообразным), получаем итоговую сложность последовательной реализации алгоритма &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt; (в предположении, что &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; существенно меньше &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Приведём аналитическое и графическое описание графа алгоритма.&lt;br /&gt;
&lt;br /&gt;
Граф алгоритма состоит из 5 различных видов вершин.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первая&#039;&#039;&#039; группа вершин отмечена символом &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039;, ей соответствует вычисление минимального расстояния до кластерных центров, включающее в себя следующую последовательность действий:&lt;br /&gt;
* независимое вычисление расстояний от заданного элемента &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; до каждого из кластерных центров;&lt;br /&gt;
* последовательное сравнение полученных значений с целью отыскания минимума;&lt;br /&gt;
* передача найденного минимального расстояния и соответствующего ему индекса кластера.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вторая&#039;&#039;&#039; группа вершин отмечена символом &#039;&#039;&#039;&#039;&#039;M&#039;&#039;&#039;&#039;&#039;, ей соответствует операция записи единички в столбец, отвечающий текущей ветке графа, в позицию, полученную на предыдущем шаге и соответствующую ближайшему кластерному центру.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Третья&#039;&#039;&#039; вершина отмечена символом &#039;&#039;&#039;&#039;&#039;J&#039;&#039;&#039;&#039;&#039;, подразумевается, что на этом этапе происходит расчёт объектной функции.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Четвертая&#039;&#039;&#039; вершина обозначена треугольным маркером и помечена &#039;&#039;&#039;&#039;&#039;if&#039;&#039;&#039;&#039;&#039;, на этом этапе происходит проверка условия достижения необходимой точности (условия остановки итерационного процесса).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Пятая&#039;&#039;&#039; соответствует операции пересчёта кластерных центров, она отмечена как &#039;&#039;&#039;&#039;&#039;{c}&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Все эти виды вершин визуально выделены в одну большую группу, поскольку все вместе они составляют одну полную итерацию алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:HardCMeans1.png|thumb|800px|center|Рисунок 1. Информационный граф алгоритма. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (&amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; стартовых значений кластерных центров и 1 значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; на каждую вершину графа), &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039; — вычисление минимального расстояния до кластерных центров (подробнее см. рисунок 2), &#039;&#039;&#039;&#039;&#039;M&#039;&#039;&#039;&#039;&#039; — запись единички в соответствующий столбец матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, &#039;&#039;&#039;&#039;&#039;J&#039;&#039;&#039;&#039;&#039; — вычисление объектной функции по результатам полученных вычислений, &#039;&#039;&#039;&#039;&#039;if&#039;&#039;&#039;&#039;&#039; — проверка условия достижения заданной точности, &#039;&#039;&#039;&#039;&#039;{c}&#039;&#039;&#039;&#039;&#039; — пересчёт кластерных центров и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; значений полученных кластерных центров).]]&lt;br /&gt;
[[File:HardCMeans2.PNG|thumb|400px|center|Рисунок 2. Подробное описание работы блока  &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039;. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (по 1 значению центра кластера на каждую из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; соответствующих вершин графа и значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;, единое для этого &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039;-блока), &#039;&#039;&#039;&#039;&#039;d1,...,dC&#039;&#039;&#039;&#039;&#039; — прямое вычисление  расстояния до кластерных центров, &#039;&#039;&#039;&#039;&#039;min&#039;&#039;&#039;&#039;&#039; — вычисление минимума двух чисел (с сохранением соответствующего минимуму кластерного индекса) и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (индекс кластерного центра, расположенного ближе всего к точке &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;, и соответствующее расстояние).]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
Для выполнения одной итерации алгоритма C средних необходимо выполнить параллельно ряд вычислений для каждого из &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; элементов:&lt;br /&gt;
&lt;br /&gt;
# Вычисление &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; расстояний между элементом и кластерными центрами.&lt;br /&gt;
# Выполнение &amp;lt;math&amp;gt;(C - 1)&amp;lt;/math&amp;gt; сравнений для определения минимального.&lt;br /&gt;
# Определение значений соответствующего рассматриваемому элементу &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; столбца матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Эта последовательность операций может быть выполнена для каждого элемента &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; входной выборки независимо и поэтому составляет основной ресурс параллелизма алгоритма.&lt;br /&gt;
&lt;br /&gt;
При этом, как можно видеть из информационного графа алгоритма, часть вычислений проводится в последовательном режиме, например, расчёт значения объектной функции &amp;lt;math&amp;gt;J&amp;lt;/math&amp;gt;. Аналогичная ситуация имеет место и с пересчётом кластерных центров — разделив эту операцию на &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; независимых процессов, мы потеряем в производительности за счёт увеличения накладных расходов, связанных с пересылкой данных и координацией вычислений.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что при малом объёме выборки и размерности системы попытка использования параллельной реализации алгоритма приведёт к понижению производительности, поскольку проведение последовательных расчётов потребует меньше времени, нежели пересылка данных (хотя бы матриц размера &amp;lt;math&amp;gt;nC&amp;lt;/math&amp;gt;, определяющих кластерные центры).&lt;br /&gt;
&lt;br /&gt;
При этом, как легко видеть, ширина [[глоссарий#Ярусно-параллельная форма графа алгоритма|ЯПФ]] составляет &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt; (если быть точнее, просто &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;). Высота ЯПФ для строгого алгоритма C средних оценивается как &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt; (предполагаем, что число итераций существенно меньше объёма выборки &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; &lt;br /&gt;
*&amp;lt;math&amp;gt;\{u_k\}_{k=1}^{N} \subset \mathbb{R}^n&amp;lt;/math&amp;gt; — исходный набор векторов;&lt;br /&gt;
*&amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; — количество кластеров (&amp;lt;math&amp;gt;2 \leqslant C \leqslant N&amp;lt;/math&amp;gt;);&lt;br /&gt;
* &#039;&#039;(опционально)&#039;&#039; &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; — пороговая точность работы алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;nN+1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
*&amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; — рядовая матрица из пространства &amp;lt;math&amp;gt;\mathbb{R}^{C \times N}&amp;lt;/math&amp;gt;.&lt;br /&gt;
*&amp;lt;math&amp;gt;\{c_k\}_{k=1}^{C}&amp;lt;/math&amp;gt; — набор построенных кластерных центров.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;C(N+n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Назначение:&#039;&#039;&#039; кластеризация больших наборов числовых данных.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Достоинства:&#039;&#039;&#039;&lt;br /&gt;
* лёгкость реализации;&lt;br /&gt;
* вычислительная простота.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Недостатки:&#039;&#039;&#039;&lt;br /&gt;
* нет гарантии, что итерационный процесс сойдётся к оптимальному решению;&lt;br /&gt;
* производительность существенно зависит от выбора начальных кластерных центров.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
Исследуем масштабируемость параллельной реализации строгого алгоритма C средних, соответствующей последовательной реализации, описанной в [[#Схема реализации последовательного алгоритма|п1.5]]. Для проведения расчётов использовались ресурсы вычислительного комплекса IBM Blue Gene/P и [https://github.com/ykomarov94/AlgoWiki собственная реализация алгоритма], поскольку в открытом доступе параллельные реализации алгоритма авторами найдены не были ([[#Существующие реализации алгоритма|п2.7]]).&lt;br /&gt;
&lt;br /&gt;
Набор и границы значений изменяемых параметров запуска реализации алгоритма:&lt;br /&gt;
&lt;br /&gt;
* число процессоров &amp;lt;math&amp;gt;[16 : 256]&amp;lt;/math&amp;gt; с шагом по степеням двойки;&lt;br /&gt;
* объём выборки &amp;lt;math&amp;gt;[10^3:10^7]&amp;lt;/math&amp;gt;  с шагом по степеням десятки;&lt;br /&gt;
* размерность системы &amp;lt;math&amp;gt;n=10&amp;lt;/math&amp;gt;;&lt;br /&gt;
* количество кластеров &amp;lt;math&amp;gt;C = 11&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве изменяемого параметра для построения графика был выбран объём выборки &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, поскольку варьирование прочих параметров существенно хуже отражает возможности применения технологии параллельных вычислений. Это связано с тем, что при малом количестве векторов время, затраченное на пересылку данных, сравнимо со временем, затрачиваемым непосредственно на расчёты; это хорошо видно на графике: при объёмах выборки, составляющих &amp;lt;math&amp;gt;10^3&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;10^4&amp;lt;/math&amp;gt; векторов, использование большего числа процессоров не приводит к приросту производительности (наоборот, производительность падает) ввиду высоких накладных расходов.&lt;br /&gt;
&lt;br /&gt;
[[file:HardCMeansPerfomance.png|thumb|center|700px|Рис.3 Реализация строгого алгоритма C средних. График производительности (GFLOPS) в зависимости от числа параллельных процессов и объёма выборки.]]&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
1)  [https://github.com/artpar/Hard-Clustering-implementation Последовательная реализация на С++ ]&lt;br /&gt;
&lt;br /&gt;
2) [http://projects.jasmeet.me/2013/03/HardCMeans.html Последовательная реализация на MatLab ]&lt;br /&gt;
&lt;br /&gt;
На момент публикации параллельных реализаций в свободном доступе обнаружено не было.&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Coctic</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE&amp;diff=18950</id>
		<title>Обсуждение участника:Светлана Лукьяненко</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE&amp;diff=18950"/>
		<updated>2016-11-22T12:28:34Z</updated>

		<summary type="html">&lt;p&gt;Coctic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Статья [[Участник:Светлана Лукьяненко/Строгий алгоритм С средних (Hard C-Means, HCM)]] =&lt;br /&gt;
* Не указан вклад каждого автора [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:57, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:05, 31 октября 2016 (MSK)&lt;br /&gt;
* Значительная часть п. 1.2  совпадает с тем же пунктом из [[Участник:Каледа Александр/Строгий алгоритм С средних (Hard C-Means)]] [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:05, 25 октября 2016 (MSK)&lt;br /&gt;
** Замечание снимается [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:05, 31 октября 2016 (MSK)&lt;br /&gt;
* В списке литературы отсутствуют выходные данные публикаций, кроме названия и автора. По приведенным данным определить конкретную публикацию не представляется возможным. Стоит добавить ссылку на оригинальную публикацию с описанием алгоритма, упомянутую в начале п.1.1 [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:57, 25 октября 2016 (MSK)&lt;br /&gt;
** Не исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:05, 31 октября 2016 (MSK)&lt;br /&gt;
* Список литературы совпадает со списком из [[Участник:Каледа Александр/Строгий алгоритм С средних (Hard C-Means)]] [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:01, 25 октября 2016 (MSK)&lt;br /&gt;
** Замечание снимается [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:05, 31 октября 2016 (MSK)&lt;br /&gt;
----------------------&lt;br /&gt;
* Комментарий от [[Участник:Юрий Комаров|Комарова Юрия]]: Сравните, пожалуйста, нашу историю работы над статьёй с историей работы над статьёй наших коллег: Каледы и его товарища. Сделав это, Вы обнаружите, что мы начали работать сразу же после выдачи задания, практически одними из первых и гораздо раньше указанных ребят, и неоднократно правили каждый из пунктов, доводя их до лучшей кондиции. За то, что пункт 1.2, как, впрочем, и другие пункты, и список литературы были составлены нами лично в процессе длительной совместной работы со [[Участник:Светлана Лукьяненко|Светланой]], отвечаю головой. Надеюсь, вопрос о плагиате больше не возникнет. В такой ситуации исправлять что-то должны явно не мы. С уважением, Комаров Юрий.&lt;br /&gt;
** В мои задачи не входить обвинять кого-то в плагиате, проводить расследования, кто у кого списал, или выяснять, кто прав, а кто нет. Меня попросили проверить статью, обращая внимание на пересечения с другими на ту же тему. В двух статьях есть общая часть, это пошло в замечания к обеим статьям. Пересечение уйдет - замечание снимется. Кто исправит текст - мне все равно. Когда в статье появится метка, что ее можно снова проверять - я сравню тексты снова. Пока текст совпадает - замечание с моей стороны остается. Есть А.С. Антонов, если он сочтет, что это замечание можно проигнорировать (в одной статье или в обеих) - он продвинет статью дальше. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 18:31, 28 октября 2016 (MSK)&lt;br /&gt;
** Если говорить о, скажем мягко, некорректном заимствовании, то ваш п 1.2 есть воспроизведение фрагмента из работы Нейского с небольшими добавлениями. У вас имеется разрешение автора на такое воспроизведение? Так что не стоит так сразу головой-то... [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 18:31, 28 октября 2016 (MSK)&lt;br /&gt;
** В общем, не стоит отвечать в таком тоне. Я могу понять возмущение, но писать надо корректнее. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 18:31, 28 октября 2016 (MSK)&lt;br /&gt;
* Вклад авторов указан, в источниках приведены ссылки. Исправлять часть статьи, которую у нас украли наши коллеги (дата создания их страницы 15 октября), должны не мы, а указанные личности. К сожалению, заставить их это сделать мы не можем, полагаю, регулирование этого вопроса нам разумнее доверить проверяющим.&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
* В списке литературы отсутствуют выходные данные публикаций, кроме названия и автора. По приведенным данным определить конкретную публикацию не представляется возможным. Стоит добавить ссылку на оригинальную публикацию с описанием алгоритма, упомянутую в начале п.1.1  [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:05, 31 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:06, 3 ноября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
* п. 2.4. Не приведена ссылка на текст анализируемой программы. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:38, 17 ноября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:28, 22 ноября 2016 (MSK)&lt;br /&gt;
* Необходимо указать характеристики программно-аппаратной платформы (какой компилятор, с какими опциями использовался, какие версии библиотек, на каких узлах проводился запуск и т.д.) [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:28, 22 ноября 2016 (MSK)&lt;br /&gt;
* В подписи к рис. 3 указано, что это &#039;&#039;График производительности ... от числа параллельных процессов&#039;&#039;, а подписи к оси указано, что по ней отложено число процессоров (Processors). Какой вариант правильный? [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:28, 22 ноября 2016 (MSK)&lt;/div&gt;</summary>
		<author><name>Coctic</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=18949</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=18949"/>
		<updated>2016-11-22T12:24:48Z</updated>

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

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

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

		<summary type="html">&lt;p&gt;Coctic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Статья [[Участник:Gkhazeeva/Нечеткий алгоритм C средних]] =&lt;br /&gt;
* Не указан вклад каждого автора [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:54, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:55, 1 ноября 2016 (MSK)&lt;br /&gt;
* п. 1.2 номера формул следует выравнивать по правому краю, а не прилеплять вплотную к формуле [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:54, 25 октября 2016 (MSK)&lt;br /&gt;
** Условно исправлено. Форматирование сделано негодными средствами, но неясно, установлены ли средства (https://en.wikipedia.org/wiki/Help:Displaying_a_formula#Equation_numbering), чтобы сделать правильно [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:55, 1 ноября 2016 (MSK)&lt;br /&gt;
*** Пробовал сделать указанными Вами средствами - на этом ресурсе указанные Вами шаблоны не заработали [[Участник:Yushin|Павел Юшин]]&lt;br /&gt;
* п. 1.3 состоит из одного предложения и не дает достаточно информации [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:54, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:55, 1 ноября 2016 (MSK)&lt;br /&gt;
* п. 1.7 приведенный рисунок не является информационным графом: не все дуги ориентированы, имеются циклы [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:54, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:55, 1 ноября 2016 (MSK)&lt;br /&gt;
* п. 1.9 не приведено оценки объема входных и выходных данных [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:54, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:55, 1 ноября 2016 (MSK)&lt;br /&gt;
* в разделе 2 отсутствуют необходимые пункты, п. 2.2 должен быть 2.7 [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:54, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:55, 1 ноября 2016 (MSK)&lt;br /&gt;
* В списке литературы 1 ссылка - скопированный шаблон без реальной ссылки, 2 ссылка - просто URL без выходных данных источника [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:54, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено частично. Ссылка 2 по-прежнему не имеет достаточных выходных данных [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:55, 1 ноября 2016 (MSK)&lt;br /&gt;
*** На сайте, где студентам выдавалось задание ( http://parallel.ru/ss16 ), данный материал предоставлялся в списке источников (номер [8]) в таком же виде, как он указан в данной статье [[Участник:Yushin|Павел Юшин]]&lt;br /&gt;
**** Не вижу никакого противоречия с тем, что я написал в замечании [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:47, 7 ноября 2016 (MSK)&lt;br /&gt;
**** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 16:34, 13 ноября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
* п. 2.4. Приведен график зависимости эффективности от параметров задачи. Не указано, о какой конкретно эффективности идет речь. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:29, 17 ноября 2016 (MSK)&lt;br /&gt;
** Была ссылка в справочный раздел с описанием эффективности&lt;br /&gt;
** Подпись под рисункам должна быть самодостаточна, без необходимости разбираться, куда была ссылка и какую ссылку искать. То же касается текста: он должен быть понятен без необходимости ходить по ссылкам, ссылки - средство предоставить дополнительную информацию, для уточнения деталей. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 16:31, 18 ноября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:24, 21 ноября 2016 (MSK)&lt;br /&gt;
* Необходимо указать характеристики программно-аппаратной платформы (какой компилятор, с какими опциями использовался, какие версии библиотек, на каких узлах проводился запуск и т.д.) [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:24, 21 ноября 2016 (MSK)&lt;/div&gt;</summary>
		<author><name>Coctic</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:Nikmedoed/%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_(Fuzzy_C-means)&amp;diff=18673</id>
		<title>Участник:Nikmedoed/Нечеткий алгоритм С-средних (Fuzzy C-means)</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:Nikmedoed/%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_(Fuzzy_C-means)&amp;diff=18673"/>
		<updated>2016-11-21T07:21:35Z</updated>

		<summary type="html">&lt;p&gt;Coctic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|{{REVISIONUSER}}}}&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм С-средних (Fuzzy C-means)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(c^2 MI + cMnI), (I&amp;lt;/math&amp;gt; - число итераций, &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - число точек, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - размерность точек (свойств на объект)&amp;lt;math&amp;gt;)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;Mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;cM&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt; O(c^2 I + cnI)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O( M )&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы: [[Участник:Nikmedoed|Н.А. Муромцев]] - перенос в вики, раздел 2, картинки, [[Участник:illusive_mike|М.С. Дворецкий]] - раздел 1&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Нечеткий алгоритм С-средних&#039;&#039;&#039; (&#039;&#039;Fuzzy C-means&#039;&#039;) - позволяет получить нечёткую кластеризацию больших наборов числовых данных, что позволяет корректно определять объекты на границах кластеров. Однако, выполнение данного алгоритма требует серьёзных вычислительных ресурсов, а также изначального задания количества кластеров. Кроме того, может возникнуть неоднозначность с объектами, удалёнными от центров всех кластеров.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Алгоритм кластеризации Fuzzy C-Means (FCM) был предложен Дж. Данном в 1973 году &amp;lt;ref&amp;gt;Dunn, J.C.: A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters. Journal of Cybernetics. 3 (1973): 32–57&amp;lt;/ref&amp;gt; и доработан Дж. Бездеком в 1981 году &amp;lt;ref&amp;gt;Bezdek, J.C.: Pattern Recognition with Fuzzy Objective Function Algorithms. Plenum Press, New York (1981). ISBN 0-306-40671-3&amp;lt;/ref&amp;gt;. В отличие от большинства существующих алгоритмов кластеризации, данный алгоритм является нечётким – каждый из объектов не входит однозначно в какой-либо кластер, а принадлежит всем кластерам с различными степенями принадлежности. Это даёт преимущества в качестве разбиения в случаях, когда кластеры находятся близко друг к другу, и большое число точек находится на их границах. Однако ценой такой нечёткости служат большие вычислительные затраты, чем у таких чётких алгоритмов, как [[Hard C-Means]] и [[K-Means]], при сохранении таких их недостатков, как априорное определение числа кластеров и отсутствие гарантии глобальной оптимальности результата.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Исходные данные: массив объектов &amp;lt;math&amp;gt;{X_k}\in{\R^n}, k=\overline{1,M}&amp;lt;/math&amp;gt;, число кластеров c, экспоненциальный вес &amp;lt;math&amp;gt;m\in{[1,\infty)}&amp;lt;/math&amp;gt;, параметр останова &amp;lt;math&amp;gt;\varepsilon&amp;gt;0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные: матрица разбиения &amp;lt;math&amp;gt;F&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;M\times c&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;\mu_{ki}\in[0,1]&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\sum^{c}_{i=1} {\mu_{ki}} = 1&amp;lt;/math&amp;gt;), центры кластеров &amp;lt;math&amp;gt;V_i&amp;lt;/math&amp;gt;, расстояния &amp;lt;math&amp;gt;D_{ki}&amp;lt;/math&amp;gt; между объектами и центрами кластеров.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Формулы метода (вычисляются последовательно на каждой итерации):&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
1. Уточнение центров кластеров по степеням принадлежности&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
&amp;amp;V_i=\frac{\sum^{M}_{k=1} {\mu^m_{ki} * X_k}}{\sum^{M}_{k=1} {\mu^m_{ki}}},i=\overline{1,c}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
2. Расчёт расстояний между новыми центрами кластеров и точками данных&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
&amp;amp;D_{ki}=\sqrt{{\lVert X_k - V_i \rVert}^2},k=\overline{1,M},i=\overline{1,c}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
3. Пересчёт степеней принадлежности объектов кластерам&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
&amp;amp;\mu_{ki}=\frac{1}{{ \sum^{c}_{j=1} \left ( {\frac{D_{ki}}{D_{kj}}} \right ) }^{{2}/{m-1}}&lt;br /&gt;
},k=\overline{1,M},i=\overline{1,c}\\&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На каждой итерации алгоритма происходит уточнение элементов матрицы &amp;lt;math&amp;gt;F&amp;lt;/math&amp;gt;. Выходом алгоритма служит матрица &amp;lt;math&amp;gt;F&amp;lt;/math&amp;gt;, к которой алгоритм сходится. Факт того, что алгоритм сошёлся, устанавливается проверкой вида &amp;lt;math&amp;gt;\max_{k = \overline{1,M},i = \overline{1,c}} {( \left | \mu_{ki} - \mu_{ki}^* \right |)} &amp;lt; \varepsilon&amp;lt;/math&amp;gt;  либо  &amp;lt;math&amp;gt;\max_{i = \overline{1,c}} {( \left | V_i - V_i^* \right |)} &amp;lt; \varepsilon&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\mu_{ki}^* (V_i^*)&amp;lt;/math&amp;gt; – значение &amp;lt;math&amp;gt;\mu_{ki}(V_i)&amp;lt;/math&amp;gt;, вычисленное на предыдущей итерации.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро алгоритма Fuzzy C-Means составляют шаги вычисления центров кластеров, расстояний между ними и точками данных и в особенности пересчёта матрицы степеней принадлежности точек данных.&lt;br /&gt;
&lt;br /&gt;
При реальном вычислении некоторые повторяющиеся вычисления могут быть устранены. Так, для шага вычисления центров кластеров величины &amp;lt;math&amp;gt;\mu_{ki}^m&amp;lt;/math&amp;gt; могут вычисляться однократно и умножаться на &amp;lt;math&amp;gt;X_k&amp;lt;/math&amp;gt; при включении в сумму, записанную в числителе. Для шага вычисления расстояний между центрами кластеров и точками, операция взятия квадратного корня не является обязательной, так как в дальнейшем на шаге вычисления степеней принадлежности можно непосредственно использовать квадраты этих расстояний, и сумма в знаменателе будет приобретать вид:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum^{c}_{j=1} {\left ( \frac{D_{ki} ^ {2}}{D_{kj} ^ {2}} \right )}^{{1}/{m-1}}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Алгоритм включает в себя три основных этапа – вычисление центров кластеров, вычисление расстояний между центрами кластеров и точками данных (включающее в себя макрооперации вычитания векторов и вычисления их норм, как правило в Евклидовом пространстве) и пересчёт матрицы принадлежности.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Последовательность исполнения алгоритма следующая:&lt;br /&gt;
&lt;br /&gt;
Инициализация происходит случайным заполнением матрицы принадлежности &amp;lt;math&amp;gt;F&amp;lt;/math&amp;gt; с соблюдением условия нормировки &amp;lt;math&amp;gt;\sum_{i=1}^c {\mu_{ki} =1}&amp;lt;/math&amp;gt; и переходом к шагу 1, либо случайным определением центров кластеров &amp;lt;math&amp;gt;V_i&amp;lt;/math&amp;gt; и переходом к шагу 2.&lt;br /&gt;
&lt;br /&gt;
Далее осуществляются итерации следующего вида:&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;math&amp;gt;V_i=\frac{\sum_{k=1}^{M} {\mu_{ki}^m * X_k}}{\sum_{k=1}^{M} {\mu_{ki}^m} },i=\overline{1,c}&amp;lt;/math&amp;gt;&lt;br /&gt;
# &amp;lt;math&amp;gt;D_{ki}=\sqrt{{\lVert X_k - V_i \rVert}^2},k=\overline{1,M},i=\overline{1,c}&amp;lt;/math&amp;gt;&lt;br /&gt;
# &amp;lt;math&amp;gt;\mu_{ki}=\frac{1}{{ \sum^{c}_{j=1} {\left ( \frac{D_{ki}}{D_{kj}} \right )} }^{{2}/{m-1}}&lt;br /&gt;
},k=\overline{1,M},i=\overline{1,c}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В конце каждой итерации проверяется условие останова вида &amp;lt;math&amp;gt;\max_{k = \overline{1,M},i = \overline{1,c}} {( \left | \mu_{ki} - \mu_{ki}^* \right |)} &amp;lt; \varepsilon&amp;lt;/math&amp;gt;, либо &amp;lt;math&amp;gt;\max_{i = \overline{1,c}} {( \left | V_i - V_i^* \right |)} &amp;lt; \varepsilon&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\mu_{ki}^* (V_i^*)&amp;lt;/math&amp;gt; – значение &amp;lt;math&amp;gt;\mu_{ki}(V_i)&amp;lt;/math&amp;gt;, вычисленное на предыдущей итерации. Если условие не выполнено, осуществляется переход к шагу 1.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
При кластеризации &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; объектов данных, представленных точками в &amp;lt;math&amp;gt;\R^n&amp;lt;/math&amp;gt;, на &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; кластеров, алгоритм Fuzzy C-Means в последовательном варианте имеет вычислительную сложность – &amp;lt;math&amp;gt;O(c^2 MI+cMnI)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;I&amp;lt;/math&amp;gt; – число итераций. Если считать размерность данных &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; малой, то эта сложность сводится к &amp;lt;math&amp;gt;O(c^2 MI)&amp;lt;/math&amp;gt;. Основной частью алгоритма в этом случае является пересчёт матрицы принадлежностей, требующий вычисления &amp;lt;math&amp;gt;cM&amp;lt;/math&amp;gt; сумм из &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; слагаемых на каждой итерации.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
Приведём граф единичной итерации алгоритма в параллельном оптимизированном варианте (метод распараллеливания взят в &amp;lt;ref&amp;gt;Kwok, T., Smith, K.,&lt;br /&gt;
Lozano, S., Taniar, D.: [http://num-meth.srcc.msu.ru/zhurnal/tom_2012/pdf/v13r207.pdf Parallel Fuzzy c-Means Clustering for Large Data Sets], последнее обращение 25.10.2016&amp;lt;/ref&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
[[File:C-means_paralle_graph.png|thumb|upright=2.5|frame|center|alt=Paralel Fuzzy C-Means|Каждая вершина данного графа соответствует операциям из алгоритма, указанным при помощи указанных формул. Каждый из p столбцов соответствует работе одного из процессов. Пометки справа указывают число повторений каждого узла в ходе одной итерации.]]&lt;br /&gt;
&lt;br /&gt;
Раздел 1.8 уточняет, соответствуют ли эти повторения однотипным ярусам или точкам данных, вычисления для которых можно распараллелить и далее.&lt;br /&gt;
&lt;br /&gt;
Каждый процесс обладает следующими данными:&lt;br /&gt;
* координатами точек данных &amp;lt;math&amp;gt;X_k&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;k=\overline{1+rnk* \frac{M}{p},rnk*(\frac{M}{p}+1)}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;rnk&amp;lt;/math&amp;gt; – номер процесса,&lt;br /&gt;
* значениями &amp;lt;math&amp;gt;\mu_{ki}&amp;lt;/math&amp;gt; степени принадлежности для своих точек (&amp;lt;math&amp;gt;k=\overline{1+rnk* \frac{M}{p},rnk*(\frac{M}{p} +1)}, i=\overline{1,c}&amp;lt;/math&amp;gt;),&lt;br /&gt;
* координатами центров кластеров &amp;lt;math&amp;gt;V_i&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;i=\overline{1,c}&amp;lt;/math&amp;gt;.&lt;br /&gt;
Суммы &amp;lt;math&amp;gt;\sum_{k=1+rnk*\frac{M}{p}}^{rnk * ( \frac{M}{p} +1 )} {\mu_{ki}^m}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\sum_{k=1+rnk*\frac{M}{p}}^{rnk * ( \frac{M}{p} +1 )} {\mu_{ki}^m X_k}&amp;lt;/math&amp;gt; вычисляются одновременно, поэтому значения &amp;lt;math&amp;gt;\mu_{ki}^m&amp;lt;/math&amp;gt; вычисляются по одному разу за итерацию. Таким образом, второй ярус операций на рисунке на деле не содержит операций возведения в степень.&lt;br /&gt;
За счёт линейности большинства выражений относительно данных по точкам, процессы взаимодействуют только при редукции сумм, составляющих &amp;lt;math&amp;gt;V_i&amp;lt;/math&amp;gt;. Всё остальное время каждый процессор работает только со своими &amp;lt;math&amp;gt;\frac{M}{p}&amp;lt;/math&amp;gt; точками. Это обеспечивает применимость алгоритма для больших &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
При распараллеливании по точкам исходных данных и условии останову по малому изменению степеней принадлежности выполнение одной итерации алгоритма FCM может быть разделено на следующие ярусы:&lt;br /&gt;
* &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; ярусов нахождения частичных сумм знаменателя (по &amp;lt;math&amp;gt;\frac{M}{p}-1&amp;lt;/math&amp;gt; сложений, &amp;lt;math&amp;gt;\frac{M}{p}&amp;lt;/math&amp;gt; операций возведения в степень на процесс),&lt;br /&gt;
* &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; ярусов нахождения частичных сумм числителя (по &amp;lt;math&amp;gt;\frac{M}{p} -1&amp;lt;/math&amp;gt; сложений, &amp;lt;math&amp;gt;\frac{M}{p}&amp;lt;/math&amp;gt; умножений на процесс),&lt;br /&gt;
* &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; редукции сумм и передач значений &amp;lt;math&amp;gt;V_i&amp;lt;/math&amp;gt; процессам (получение &amp;lt;math&amp;gt;c(n+1)&amp;lt;/math&amp;gt; значений, &amp;lt;math&amp;gt;cn&amp;lt;/math&amp;gt; делений),&lt;br /&gt;
* &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; ярусов вычисления расстояний до центров (по &amp;lt;math&amp;gt;n-1&amp;lt;/math&amp;gt; сложений, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; вычитаний, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений), каждый процесс получает &amp;lt;math&amp;gt;\frac{M}{p}&amp;lt;/math&amp;gt; точек на обработку,&lt;br /&gt;
* &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; ярусов вычисления степеней принадлежности точек (по &amp;lt;math&amp;gt;c+1&amp;lt;/math&amp;gt; делений, c возведений в степень, &amp;lt;math&amp;gt;c-1&amp;lt;/math&amp;gt; сложений), каждый процесс получает &amp;lt;math&amp;gt;\frac{M}{p}&amp;lt;/math&amp;gt; точек на обработку,&lt;br /&gt;
* до &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; ярусов проверки условий останова (по &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; вычитанию, &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; сравнению), каждый процесс получает &amp;lt;math&amp;gt;\frac{M}{p}&amp;lt;/math&amp;gt; точек на обработку,&lt;br /&gt;
* &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; редукция для обмена статусом завершения.&lt;br /&gt;
Таким образом, при распараллеливании по точкам исходных данных при условии наличия в каждом узле достаточного объёма памяти для хранения всего массива координат центров кластеров высота и ширина ЯПФ алгоритма FCM равны соответственно &amp;lt;math&amp;gt;O(c^2 I+cnI)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;O(M)&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;X_i&amp;lt;/math&amp;gt;, число кластеров &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;, экспоненциальный вес &amp;lt;math&amp;gt;m\in{[1,\infty)}&amp;lt;/math&amp;gt;, параметр останова &amp;lt;math&amp;gt;\varepsilon&amp;gt;0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;Mn&amp;lt;/math&amp;gt; для входных векторов, 3 вспомогательных параметра.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица принадлежности &amp;lt;math&amp;gt;F&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;\mu_{ki}\in[0,1]&amp;lt;/math&amp;gt;). Условие нормировки: &amp;lt;math&amp;gt;\sum^{c}_{i=1} {\mu_{ki}} = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;cM&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
В случае неограниченного распараллеливания по точкам данных (1 процесс на точку), отношение последовательной сложности алгоритма к параллельной пропорционально &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Параметр &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; задаёт степень «размытости» кластеров. В отсутствие априорных данных его обычно берут равным 2. В предельном случае сведения параметра &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; к значению 1, кластеры становятся чёткими и алгоритм вырождается в алгоритм кластеризации K-Means.&lt;br /&gt;
&lt;br /&gt;
Алгоритм недетерминирован, начальное положение кластеров задаётся случайно либо явно, либо опосредованно (через матрицу принадлежности). Алгоритм сходится к локальному экстремуму &amp;lt;ref&amp;gt;Höppner, F., Klawonn, F.: [https://public.fh wolfenbuettel.de/~klawonn/Papers/hoeppnerklawonntfs03.pdf A Contribution to Convergence Theory of Fuzzy c-Means and Derivatives], Дата последнего обращения: 13.10.2016&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;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
[[File:График.png|thumb|upright=2.5|frame|right|alt=Paralel Fuzzy C-Means time to iteration|График зависимости времени выполнения итерации параллельного нечеткого алгоритма С-средних (Fuzzy C-means) от количества процессоров и количества кластеризуемых вершин]]&lt;br /&gt;
&lt;br /&gt;
[[File:Effect_parallel_fuzzy_c-means.png|thumb|upright=2.5|frame|right|alt=Paralel Fuzzy C-Means efficiency|График эффективности распараллеливания нечеткого алгоритма С-средних (Fuzzy C-means) в зависимости от количества процессоров и количества кластеризуемых вершин.]]&lt;br /&gt;
&lt;br /&gt;
Исследование проведено на суперкомпьютере IBM Blue Gene/P&amp;lt;ref&amp;gt;[http://hpc.cs.msu.ru/bgp Описание вычислительного комплекса IBM Blue Gene/P]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
Для исследования была использована последовательная реализация алгоритма и реализован её [https://github.com/IllusiveMike/Parallel-Fuzzy-C-means/tree/patch-1 параллельный вариант]&amp;lt;ref&amp;gt;[https://github.com/nikmedoed/Parallel-Fuzzy-C-means Параллельная реализация алгоритма Fuzzy C-Means]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
Алгоритм обладает плохо исследованной сходимостью, но объем вычислений на итерации не зависит от значений данных, поэтому данное исследование масштабируемости было произведено для единичной итерации.&lt;br /&gt;
&lt;br /&gt;
Для упрощения экспериментов было решено использовать количество вершин для кластеризации и количество процессов равное степени двойки, поэтому для каждого эксперимента были выбраны значения:&lt;br /&gt;
* &amp;lt;math&amp;gt;2^v, v=\overline{0,9}&amp;lt;/math&amp;gt;, для количества процессоров;&lt;br /&gt;
* &amp;lt;math&amp;gt;2^w, w=\overline{10,20}&amp;lt;/math&amp;gt;, для количества кластеризуемых вершин.&lt;br /&gt;
&lt;br /&gt;
Для одного набора значений проводилось 4 эксперимента и результаты усреднялись. При повторных запусках экспериментов значения выходили те же самые.&lt;br /&gt;
&lt;br /&gt;
Полученные результаты говорят о хорошей масштабируемости реализации алгоритма. Для большинства экспериментов эффективность распараллеливания находится в пределах 100±3%. Высокая эффективность обуславливается тем, что данные равномерно распределены по процессорам и на каждой итерации требуется глобальная редукция всего &amp;lt;math&amp;gt;2c+1&amp;lt;/math&amp;gt; значений (&amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; значений числителей центроид кластеров, &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; значений знаменателей центроид кластеров и одно значение признака останова). Таким образом вычисления занимают значительно больше времени, чем взаимодействия между процессами, которые практически не приводят к простоям из-за хорошей балансировки. Спад эффективности при малом числе вершин и большом числе процессоров обуславливается тем, что с уменьшением числа вершин, обрабатываемых каждым процессором, растёт доля времени обмена данных между процессорами, не зависящего от числа вершин, как показано выше.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
* пакет MATLAB &amp;lt;ref&amp;gt;[http://www.mathworks.com/help/fuzzy/fcm.html Документация пакета MATLAB, функция fcm], последнее обращение 15.10.2016&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Реализация алгоритма на POSTGRESQL &amp;lt;ref&amp;gt;[http://num-meth.srcc.msu.ru/zhurnal/tom_2012/pdf/v13r207.pdf Реализация алгоритма Fuzzy C-means на POSTGRESQL], последнее обращение 15.10.2016&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&lt;br /&gt;
[[en:Parallel Fuzzy c-Means Clustering]]&lt;/div&gt;</summary>
		<author><name>Coctic</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Nikmedoed&amp;diff=18672</id>
		<title>Обсуждение участника:Nikmedoed</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Nikmedoed&amp;diff=18672"/>
		<updated>2016-11-21T07:17:32Z</updated>

		<summary type="html">&lt;p&gt;Coctic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Статья [[Участник:Nikmedoed/Нечеткий алгоритм С-средних (Fuzzy C-means)]] =&lt;br /&gt;
* не указан вклад каждого автора [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:01, 25 октября 2016 (MSK)&lt;br /&gt;
** Могли бы вы подсказать в каком формате это сделать? Просто общее сообщение, либо в каждом пункте указать?&lt;br /&gt;
*** В начале написать &amp;quot;Авторы: Автор1 - раздел 1, Автор2 - раздел 2&amp;quot;. Ну или что-то в том духе. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 18:01, 28 октября 2016 (MSK)&lt;br /&gt;
:::: Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:32, 31 октября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
* п. 1.2 приведен набор формул, однако отсутствует пояснения, как эти формулы складываются в алгоритм [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:01, 25 октября 2016 (MSK)&lt;br /&gt;
** П. 1.2 расширен в соответствии с замечанием. Ожидаю отзыв. [[Участник:Illusive_mike|Дворецкий М.С.]] ([[Обсуждение участника:Illusive_mike|обсуждение]]) 15:46, 25 октября 2016 (MSK)&lt;br /&gt;
::: Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:32, 31 октября 2016 (MSK)&lt;br /&gt;
----------------&lt;br /&gt;
* п. 2.4. проведены исследования масштабируемости одной итерации. Исследование масштабируемости реализации в целом отсутствует [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:27, 17 ноября 2016 (MSK)&lt;br /&gt;
** Добавлено в статью: &amp;quot;Алгоритм обладает плохо исследованной сходимостью, но объем вычислений и итераций не зависит от значений данных, поэтому данное исследование масштабируемости было произведено для единичной итерации.&amp;quot;&lt;br /&gt;
** Принято [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:41, 18 ноября 2016 (MSK)&lt;br /&gt;
* п. 2.4. Рис. 2 приведен график зависимости эффективности от параметров задачи. Не указано, о каком виде эффективности идет речь. Значение эффективности в 100% в реальности встречается очень редко, надо в тексте пояснить, почему такой хороший результат. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:27, 17 ноября 2016 (MSK)&lt;br /&gt;
** Добавили пояснение, что это график временной эффективности&lt;br /&gt;
** Что такое временная эффективность? В [[Глоссарий|глоссарии]] такой нет. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:41, 18 ноября 2016 (MSK)&lt;br /&gt;
*** Изменено на термин из глоссария - эффективность распараллеливания.&lt;br /&gt;
** Добавили пояснение про причину высокой временной эффективности&lt;br /&gt;
** Принято [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 16:40, 18 ноября 2016 (MSK)&lt;br /&gt;
* п. 2.4. &#039;&#039;Для большинства экспериментов эффективность находится в пределах 100±3%.&#039;&#039;. Как эффективность может быть больше 100%? [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:27, 17 ноября 2016 (MSK)&lt;br /&gt;
** Сверхлинейное ускорение&lt;br /&gt;
** [https://www.dropbox.com/s/2ijzr6g8mhrftts/%D0%B8%D1%82%D0%BE%D0%B3%D0%B8%20%D1%82%D0%B5%D1%81%D1%82%D0%B0.xlsx?dl=0 Ссылка на расчёты]&lt;br /&gt;
** Доступная нам система профилировки недостаточна, чтобы найти причину сверхлинейного ускорения точно, поэтому мы не упомянули её прямым текстом&lt;br /&gt;
** Сначала надо разобраться, какая эффективность имеется в виду. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:41, 18 ноября 2016 (MSK)&lt;br /&gt;
** Принято [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 16:40, 18 ноября 2016 (MSK)&lt;br /&gt;
* П. 2.4. Необходимо добавить описание ключей компилятора, особенностей запуска (раздел, используемые вычислительные узлы и т.п. информация, достаточная для воспроизведения данных). [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 16:40, 18 ноября 2016 (MSK)&lt;br /&gt;
** Добавлен файл README в проекте на GitHub. Это исправление мой товарищ сделал ещё 18, т.к. у меня не было доступа к чему-либо до вчера. А теперь обновил я ссылку.&lt;br /&gt;
** Принято [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:17, 21 ноября 2016 (MSK)&lt;/div&gt;</summary>
		<author><name>Coctic</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:Nikmedoed/%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_(Fuzzy_C-means)&amp;diff=18143</id>
		<title>Участник:Nikmedoed/Нечеткий алгоритм С-средних (Fuzzy C-means)</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:Nikmedoed/%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_(Fuzzy_C-means)&amp;diff=18143"/>
		<updated>2016-11-18T13:40:24Z</updated>

		<summary type="html">&lt;p&gt;Coctic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм С-средних (Fuzzy C-means)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(c^2 MI + cMnI), (I&amp;lt;/math&amp;gt; - число итераций, &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - число точек, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - размерность точек (свойств на объект)&amp;lt;math&amp;gt;)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;Mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;cM&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt; O(c^2 I + cnI)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O( M )&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы: [[Участник:Nikmedoed|Н.А. Муромцев]] - перенос в вики, раздел 2, картинки, [[Участник:illusive_mike|М.С. Дворецкий]] - раздел 1&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Нечеткий алгоритм С-средних&#039;&#039;&#039; (&#039;&#039;Fuzzy C-means&#039;&#039;) - позволяет получить нечёткую кластеризацию больших наборов числовых данных, что позволяет корректно определять объекты на границах кластеров. Однако, выполнение данного алгоритма требует серьёзных вычислительных ресурсов, а также изначального задания количества кластеров. Кроме того, может возникнуть неоднозначность с объектами, удалёнными от центров всех кластеров.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Алгоритм кластеризации Fuzzy C-Means (FCM) был предложен Дж. Данном в 1973 году &amp;lt;ref&amp;gt;Dunn, J.C.: A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters. Journal of Cybernetics. 3 (1973): 32–57&amp;lt;/ref&amp;gt; и доработан Дж. Бездеком в 1981 году &amp;lt;ref&amp;gt;Bezdek, J.C.: Pattern Recognition with Fuzzy Objective Function Algorithms. Plenum Press, New York (1981). ISBN 0-306-40671-3&amp;lt;/ref&amp;gt;. В отличие от большинства существующих алгоритмов кластеризации, данный алгоритм является нечётким – каждый из объектов не входит однозначно в какой-либо кластер, а принадлежит всем кластерам с различными степенями принадлежности. Это даёт преимущества в качестве разбиения в случаях, когда кластеры находятся близко друг к другу, и большое число точек находится на их границах. Однако ценой такой нечёткости служат большие вычислительные затраты, чем у таких чётких алгоритмов, как [[Hard C-Means]] и [[K-Means]], при сохранении таких их недостатков, как априорное определение числа кластеров и отсутствие гарантии глобальной оптимальности результата.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Исходные данные: массив объектов &amp;lt;math&amp;gt;{X_k}\in{\R^n}, k=\overline{1,M}&amp;lt;/math&amp;gt;, число кластеров c, экспоненциальный вес &amp;lt;math&amp;gt;m\in{[1,\infty)}&amp;lt;/math&amp;gt;, параметр останова &amp;lt;math&amp;gt;\varepsilon&amp;gt;0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные: матрица разбиения &amp;lt;math&amp;gt;F&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;M\times c&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;\mu_{ki}\in[0,1]&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\sum^{c}_{i=1} {\mu_{ki}} = 1&amp;lt;/math&amp;gt;), центры кластеров &amp;lt;math&amp;gt;V_i&amp;lt;/math&amp;gt;, расстояния &amp;lt;math&amp;gt;D_{ki}&amp;lt;/math&amp;gt; между объектами и центрами кластеров.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Формулы метода (вычисляются последовательно на каждой итерации):&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
1. Уточнение центров кластеров по степеням принадлежности&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
&amp;amp;V_i=\frac{\sum^{M}_{k=1} {\mu^m_{ki} * X_k}}{\sum^{M}_{k=1} {\mu^m_{ki}}},i=\overline{1,c}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
2. Расчёт расстояний между новыми центрами кластеров и точками данных&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
&amp;amp;D_{ki}=\sqrt{{\lVert X_k - V_i \rVert}^2},k=\overline{1,M},i=\overline{1,c}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
3. Пересчёт степеней принадлежности объектов кластерам&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
&amp;amp;\mu_{ki}=\frac{1}{{ \sum^{c}_{j=1} \left ( {\frac{D_{ki}}{D_{kj}}} \right ) }^{{2}/{m-1}}&lt;br /&gt;
},k=\overline{1,M},i=\overline{1,c}\\&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На каждой итерации алгоритма происходит уточнение элементов матрицы &amp;lt;math&amp;gt;F&amp;lt;/math&amp;gt;. Выходом алгоритма служит матрица &amp;lt;math&amp;gt;F&amp;lt;/math&amp;gt;, к которой алгоритм сходится. Факт того, что алгоритм сошёлся, устанавливается проверкой вида &amp;lt;math&amp;gt;\max_{k = \overline{1,M},i = \overline{1,c}} {( \left | \mu_{ki} - \mu_{ki}^* \right |)} &amp;lt; \varepsilon&amp;lt;/math&amp;gt;  либо  &amp;lt;math&amp;gt;\max_{i = \overline{1,c}} {( \left | V_i - V_i^* \right |)} &amp;lt; \varepsilon&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\mu_{ki}^* (V_i^*)&amp;lt;/math&amp;gt; – значение &amp;lt;math&amp;gt;\mu_{ki}(V_i)&amp;lt;/math&amp;gt;, вычисленное на предыдущей итерации.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро алгоритма Fuzzy C-Means составляют шаги вычисления центров кластеров, расстояний между ними и точками данных и в особенности пересчёта матрицы степеней принадлежности точек данных.&lt;br /&gt;
&lt;br /&gt;
При реальном вычислении некоторые повторяющиеся вычисления могут быть устранены. Так, для шага вычисления центров кластеров величины &amp;lt;math&amp;gt;\mu_{ki}^m&amp;lt;/math&amp;gt; могут вычисляться однократно и умножаться на &amp;lt;math&amp;gt;X_k&amp;lt;/math&amp;gt; при включении в сумму, записанную в числителе. Для шага вычисления расстояний между центрами кластеров и точками, операция взятия квадратного корня не является обязательной, так как в дальнейшем на шаге вычисления степеней принадлежности можно непосредственно использовать квадраты этих расстояний, и сумма в знаменателе будет приобретать вид:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum^{c}_{j=1} {\left ( \frac{D_{ki} ^ {2}}{D_{kj} ^ {2}} \right )}^{{1}/{m-1}}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Алгоритм включает в себя три основных этапа – вычисление центров кластеров, вычисление расстояний между центрами кластеров и точками данных (включающее в себя макрооперации вычитания векторов и вычисления их норм, как правило в Евклидовом пространстве) и пересчёт матрицы принадлежности.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Последовательность исполнения алгоритма следующая:&lt;br /&gt;
&lt;br /&gt;
Инициализация происходит случайным заполнением матрицы принадлежности &amp;lt;math&amp;gt;F&amp;lt;/math&amp;gt; с соблюдением условия нормировки &amp;lt;math&amp;gt;\sum_{i=1}^c {\mu_{ki} =1}&amp;lt;/math&amp;gt; и переходом к шагу 1, либо случайным определением центров кластеров &amp;lt;math&amp;gt;V_i&amp;lt;/math&amp;gt; и переходом к шагу 2.&lt;br /&gt;
&lt;br /&gt;
Далее осуществляются итерации следующего вида:&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;math&amp;gt;V_i=\frac{\sum_{k=1}^{M} {\mu_{ki}^m * X_k}}{\sum_{k=1}^{M} {\mu_{ki}^m} },i=\overline{1,c}&amp;lt;/math&amp;gt;&lt;br /&gt;
# &amp;lt;math&amp;gt;D_{ki}=\sqrt{{\lVert X_k - V_i \rVert}^2},k=\overline{1,M},i=\overline{1,c}&amp;lt;/math&amp;gt;&lt;br /&gt;
# &amp;lt;math&amp;gt;\mu_{ki}=\frac{1}{{ \sum^{c}_{j=1} {\left ( \frac{D_{ki}}{D_{kj}} \right )} }^{{2}/{m-1}}&lt;br /&gt;
},k=\overline{1,M},i=\overline{1,c}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В конце каждой итерации проверяется условие останова вида &amp;lt;math&amp;gt;\max_{k = \overline{1,M},i = \overline{1,c}} {( \left | \mu_{ki} - \mu_{ki}^* \right |)} &amp;lt; \varepsilon&amp;lt;/math&amp;gt;, либо &amp;lt;math&amp;gt;\max_{i = \overline{1,c}} {( \left | V_i - V_i^* \right |)} &amp;lt; \varepsilon&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\mu_{ki}^* (V_i^*)&amp;lt;/math&amp;gt; – значение &amp;lt;math&amp;gt;\mu_{ki}(V_i)&amp;lt;/math&amp;gt;, вычисленное на предыдущей итерации. Если условие не выполнено, осуществляется переход к шагу 1.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
При кластеризации &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; объектов данных, представленных точками в &amp;lt;math&amp;gt;\R^n&amp;lt;/math&amp;gt;, на &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; кластеров, алгоритм Fuzzy C-Means в последовательном варианте имеет вычислительную сложность – &amp;lt;math&amp;gt;O(c^2 MI+cMnI)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;I&amp;lt;/math&amp;gt; – число итераций. Если считать размерность данных &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; малой, то эта сложность сводится к &amp;lt;math&amp;gt;O(c^2 MI)&amp;lt;/math&amp;gt;. Основной частью алгоритма в этом случае является пересчёт матрицы принадлежностей, требующий вычисления &amp;lt;math&amp;gt;cM&amp;lt;/math&amp;gt; сумм из &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; слагаемых на каждой итерации.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
Приведём граф единичной итерации алгоритма в параллельном оптимизированном варианте (метод распараллеливания взят в &amp;lt;ref&amp;gt;Kwok, T., Smith, K.,&lt;br /&gt;
Lozano, S., Taniar, D.: [http://num-meth.srcc.msu.ru/zhurnal/tom_2012/pdf/v13r207.pdf Parallel Fuzzy c-Means Clustering for Large Data Sets], последнее обращение 25.10.2016&amp;lt;/ref&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
[[File:C-means_paralle_graph.png|thumb|upright=2.5|frame|center|alt=Paralel Fuzzy C-Means|Каждая вершина данного графа соответствует операциям из алгоритма, указанным при помощи указанных формул. Каждый из p столбцов соответствует работе одного из процессов. Пометки справа указывают число повторений каждого узла в ходе одной итерации.]]&lt;br /&gt;
&lt;br /&gt;
Раздел 1.8 уточняет, соответствуют ли эти повторения однотипным ярусам или точкам данных, вычисления для которых можно распараллелить и далее.&lt;br /&gt;
&lt;br /&gt;
Каждый процесс обладает следующими данными:&lt;br /&gt;
* координатами точек данных &amp;lt;math&amp;gt;X_k&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;k=\overline{1+rnk* \frac{M}{p},rnk*(\frac{M}{p}+1)}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;rnk&amp;lt;/math&amp;gt; – номер процесса,&lt;br /&gt;
* значениями &amp;lt;math&amp;gt;\mu_{ki}&amp;lt;/math&amp;gt; степени принадлежности для своих точек (&amp;lt;math&amp;gt;k=\overline{1+rnk* \frac{M}{p},rnk*(\frac{M}{p} +1)}, i=\overline{1,c}&amp;lt;/math&amp;gt;),&lt;br /&gt;
* координатами центров кластеров &amp;lt;math&amp;gt;V_i&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;i=\overline{1,c}&amp;lt;/math&amp;gt;.&lt;br /&gt;
Суммы &amp;lt;math&amp;gt;\sum_{k=1+rnk*\frac{M}{p}}^{rnk * ( \frac{M}{p} +1 )} {\mu_{ki}^m}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\sum_{k=1+rnk*\frac{M}{p}}^{rnk * ( \frac{M}{p} +1 )} {\mu_{ki}^m X_k}&amp;lt;/math&amp;gt; вычисляются одновременно, поэтому значения &amp;lt;math&amp;gt;\mu_{ki}^m&amp;lt;/math&amp;gt; вычисляются по одному разу за итерацию. Таким образом, второй ярус операций на рисунке на деле не содержит операций возведения в степень.&lt;br /&gt;
За счёт линейности большинства выражений относительно данных по точкам, процессы взаимодействуют только при редукции сумм, составляющих &amp;lt;math&amp;gt;V_i&amp;lt;/math&amp;gt;. Всё остальное время каждый процессор работает только со своими &amp;lt;math&amp;gt;\frac{M}{p}&amp;lt;/math&amp;gt; точками. Это обеспечивает применимость алгоритма для больших &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
При распараллеливании по точкам исходных данных и условии останову по малому изменению степеней принадлежности выполнение одной итерации алгоритма FCM может быть разделено на следующие ярусы:&lt;br /&gt;
* &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; ярусов нахождения частичных сумм знаменателя (по &amp;lt;math&amp;gt;\frac{M}{p}-1&amp;lt;/math&amp;gt; сложений, &amp;lt;math&amp;gt;\frac{M}{p}&amp;lt;/math&amp;gt; операций возведения в степень на процесс),&lt;br /&gt;
* &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; ярусов нахождения частичных сумм числителя (по &amp;lt;math&amp;gt;\frac{M}{p} -1&amp;lt;/math&amp;gt; сложений, &amp;lt;math&amp;gt;\frac{M}{p}&amp;lt;/math&amp;gt; умножений на процесс),&lt;br /&gt;
* &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; редукции сумм и передач значений &amp;lt;math&amp;gt;V_i&amp;lt;/math&amp;gt; процессам (получение &amp;lt;math&amp;gt;c(n+1)&amp;lt;/math&amp;gt; значений, &amp;lt;math&amp;gt;cn&amp;lt;/math&amp;gt; делений),&lt;br /&gt;
* &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; ярусов вычисления расстояний до центров (по &amp;lt;math&amp;gt;n-1&amp;lt;/math&amp;gt; сложений, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; вычитаний, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений), каждый процесс получает &amp;lt;math&amp;gt;\frac{M}{p}&amp;lt;/math&amp;gt; точек на обработку,&lt;br /&gt;
* &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; ярусов вычисления степеней принадлежности точек (по &amp;lt;math&amp;gt;c+1&amp;lt;/math&amp;gt; делений, c возведений в степень, &amp;lt;math&amp;gt;c-1&amp;lt;/math&amp;gt; сложений), каждый процесс получает &amp;lt;math&amp;gt;\frac{M}{p}&amp;lt;/math&amp;gt; точек на обработку,&lt;br /&gt;
* до &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; ярусов проверки условий останова (по &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; вычитанию, &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; сравнению), каждый процесс получает &amp;lt;math&amp;gt;\frac{M}{p}&amp;lt;/math&amp;gt; точек на обработку,&lt;br /&gt;
* &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; редукция для обмена статусом завершения.&lt;br /&gt;
Таким образом, при распараллеливании по точкам исходных данных при условии наличия в каждом узле достаточного объёма памяти для хранения всего массива координат центров кластеров высота и ширина ЯПФ алгоритма FCM равны соответственно &amp;lt;math&amp;gt;O(c^2 I+cnI)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;O(M)&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;X_i&amp;lt;/math&amp;gt;, число кластеров &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;, экспоненциальный вес &amp;lt;math&amp;gt;m\in{[1,\infty)}&amp;lt;/math&amp;gt;, параметр останова &amp;lt;math&amp;gt;\varepsilon&amp;gt;0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;Mn&amp;lt;/math&amp;gt; для входных векторов, 3 вспомогательных параметра.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица принадлежности &amp;lt;math&amp;gt;F&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;\mu_{ki}\in[0,1]&amp;lt;/math&amp;gt;). Условие нормировки: &amp;lt;math&amp;gt;\sum^{c}_{i=1} {\mu_{ki}} = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;cM&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
В случае неограниченного распараллеливания по точкам данных (1 процесс на точку), отношение последовательной сложности алгоритма к параллельной пропорционально &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Параметр &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; задаёт степень «размытости» кластеров. В отсутствие априорных данных его обычно берут равным 2. В предельном случае сведения параметра &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; к значению 1, кластеры становятся чёткими и алгоритм вырождается в алгоритм кластеризации K-Means.&lt;br /&gt;
&lt;br /&gt;
Алгоритм недетерминирован, начальное положение кластеров задаётся случайно либо явно, либо опосредованно (через матрицу принадлежности). Алгоритм сходится к локальному экстремуму &amp;lt;ref&amp;gt;Höppner, F., Klawonn, F.: [https://public.fh wolfenbuettel.de/~klawonn/Papers/hoeppnerklawonntfs03.pdf A Contribution to Convergence Theory of Fuzzy c-Means and Derivatives], Дата последнего обращения: 13.10.2016&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;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
[[File:График.png|thumb|upright=2.5|frame|right|alt=Paralel Fuzzy C-Means time to iteration|График зависимости времени выполнения итерации параллельного нечеткого алгоритма С-средних (Fuzzy C-means) от количества процессоров и количества кластеризуемых вершин]]&lt;br /&gt;
&lt;br /&gt;
[[File:Effect_parallel_fuzzy_c-means.png|thumb|upright=2.5|frame|right|alt=Paralel Fuzzy C-Means efficiency|График эффективности распараллеливания нечеткого алгоритма С-средних (Fuzzy C-means) в зависимости от количества процессоров и количества кластеризуемых вершин.]]&lt;br /&gt;
&lt;br /&gt;
Исследование проведено на суперкомпьютере IBM Blue Gene/P&amp;lt;ref&amp;gt;[http://hpc.cs.msu.ru/bgp Описание вычислительного комплекса IBM Blue Gene/P]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
Для исследования была использована последовательная реализация алгоритма и реализован её [https://github.com/nikmedoed/Parallel-Fuzzy-C-means параллельный вариант]&amp;lt;ref&amp;gt;[https://github.com/nikmedoed/Parallel-Fuzzy-C-means Параллельная реализация алгоритма Fuzzy C-Means]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
Алгоритм обладает плохо исследованной сходимостью, но объем вычислений на итерации не зависит от значений данных, поэтому данное исследование масштабируемости было произведено для единичной итерации.&lt;br /&gt;
&lt;br /&gt;
Для упрощения экспериментов было решено использовать количество вершин для кластеризации и количество процессов равное степени двойки, поэтому для каждого эксперимента были выбраны значения:&lt;br /&gt;
* &amp;lt;math&amp;gt;2^v, v=\overline{0,9}&amp;lt;/math&amp;gt;, для количества процессоров;&lt;br /&gt;
* &amp;lt;math&amp;gt;2^w, w=\overline{10,20}&amp;lt;/math&amp;gt;, для количества кластеризуемых вершин.&lt;br /&gt;
&lt;br /&gt;
Для одного набора значений проводилось 4 эксперимента и результаты усреднялись. При повторных запусках экспериментов значения выходили те же самые.&lt;br /&gt;
&lt;br /&gt;
Полученные результаты говорят о хорошей масштабируемости реализации алгоритма. Для большинства экспериментов эффективность распараллеливания находится в пределах 100±3%. Высокая эффективность обуславливается тем, что данные равномерно распределены по процессорам и на каждой итерации требуется глобальная редукция всего &amp;lt;math&amp;gt;2c+1&amp;lt;/math&amp;gt; значений (&amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; значений числителей центроид кластеров, &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; значений знаменателей центроид кластеров и одно значение признака останова). Таким образом вычисления занимают значительно больше времени, чем взаимодействия между процессами, которые практически не приводят к простоям из-за хорошей балансировки. Спад эффективности при малом числе вершин и большом числе процессоров обуславливается тем, что с уменьшением числа вершин, обрабатываемых каждым процессором, растёт доля времени обмена данных между процессорами, не зависящего от числа вершин, как показано выше.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
* пакет MATLAB &amp;lt;ref&amp;gt;[http://www.mathworks.com/help/fuzzy/fcm.html Документация пакета MATLAB, функция fcm], последнее обращение 15.10.2016&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Реализация алгоритма на POSTGRESQL &amp;lt;ref&amp;gt;[http://num-meth.srcc.msu.ru/zhurnal/tom_2012/pdf/v13r207.pdf Реализация алгоритма Fuzzy C-means на POSTGRESQL], последнее обращение 15.10.2016&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&lt;br /&gt;
[[en:Parallel Fuzzy c-Means Clustering]]&lt;/div&gt;</summary>
		<author><name>Coctic</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Nikmedoed&amp;diff=18142</id>
		<title>Обсуждение участника:Nikmedoed</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Nikmedoed&amp;diff=18142"/>
		<updated>2016-11-18T13:40:12Z</updated>

		<summary type="html">&lt;p&gt;Coctic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Статья [[Участник:Nikmedoed/Нечеткий алгоритм С-средних (Fuzzy C-means)]] =&lt;br /&gt;
* не указан вклад каждого автора [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:01, 25 октября 2016 (MSK)&lt;br /&gt;
** Могли бы вы подсказать в каком формате это сделать? Просто общее сообщение, либо в каждом пункте указать?&lt;br /&gt;
*** В начале написать &amp;quot;Авторы: Автор1 - раздел 1, Автор2 - раздел 2&amp;quot;. Ну или что-то в том духе. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 18:01, 28 октября 2016 (MSK)&lt;br /&gt;
:::: Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:32, 31 октября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
* п. 1.2 приведен набор формул, однако отсутствует пояснения, как эти формулы складываются в алгоритм [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:01, 25 октября 2016 (MSK)&lt;br /&gt;
** П. 1.2 расширен в соответствии с замечанием. Ожидаю отзыв. [[Участник:Illusive_mike|Дворецкий М.С.]] ([[Обсуждение участника:Illusive_mike|обсуждение]]) 15:46, 25 октября 2016 (MSK)&lt;br /&gt;
::: Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:32, 31 октября 2016 (MSK)&lt;br /&gt;
----------------&lt;br /&gt;
* п. 2.4. проведены исследования масштабируемости одной итерации. Исследование масштабируемости реализации в целом отсутствует [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:27, 17 ноября 2016 (MSK)&lt;br /&gt;
** Добавлено в статью: &amp;quot;Алгоритм обладает плохо исследованной сходимостью, но объем вычислений и итераций не зависит от значений данных, поэтому данное исследование масштабируемости было произведено для единичной итерации.&amp;quot;&lt;br /&gt;
** Принято [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:41, 18 ноября 2016 (MSK)&lt;br /&gt;
* п. 2.4. Рис. 2 приведен график зависимости эффективности от параметров задачи. Не указано, о каком виде эффективности идет речь. Значение эффективности в 100% в реальности встречается очень редко, надо в тексте пояснить, почему такой хороший результат. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:27, 17 ноября 2016 (MSK)&lt;br /&gt;
** Добавили пояснение, что это график временной эффективности&lt;br /&gt;
** Что такое временная эффективность? В [[Глоссарий|глоссарии]] такой нет. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:41, 18 ноября 2016 (MSK)&lt;br /&gt;
*** Изменено на термин из глоссария - эффективность распараллеливания.&lt;br /&gt;
** Добавили пояснение про причину высокой временной эффективности&lt;br /&gt;
** Принято [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 16:40, 18 ноября 2016 (MSK)&lt;br /&gt;
* п. 2.4. &#039;&#039;Для большинства экспериментов эффективность находится в пределах 100±3%.&#039;&#039;. Как эффективность может быть больше 100%? [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:27, 17 ноября 2016 (MSK)&lt;br /&gt;
** Сверхлинейное ускорение&lt;br /&gt;
** [https://www.dropbox.com/s/2ijzr6g8mhrftts/%D0%B8%D1%82%D0%BE%D0%B3%D0%B8%20%D1%82%D0%B5%D1%81%D1%82%D0%B0.xlsx?dl=0 Ссылка на расчёты]&lt;br /&gt;
** Доступная нам система профилировки недостаточна, чтобы найти причину сверхлинейного ускорения точно, поэтому мы не упомянули её прямым текстом&lt;br /&gt;
** Сначала надо разобраться, какая эффективность имеется в виду. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:41, 18 ноября 2016 (MSK)&lt;br /&gt;
** Принято [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 16:40, 18 ноября 2016 (MSK)&lt;br /&gt;
* П. 2.4. Необходимо добавить описание ключей компилятора, особенностей запуска (раздел, используемые вычислительные узлы и т.п. информация, достаточная для воспроизведения данных). [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 16:40, 18 ноября 2016 (MSK)&lt;/div&gt;</summary>
		<author><name>Coctic</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Gkhazeeva&amp;diff=18141</id>
		<title>Обсуждение участника:Gkhazeeva</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Gkhazeeva&amp;diff=18141"/>
		<updated>2016-11-18T13:33:42Z</updated>

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

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

		<summary type="html">&lt;p&gt;Coctic: /* Статья Нечеткий алгоритм C средних */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Статья [[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85]] =&lt;br /&gt;
* Не указан вклад каждого автора [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:54, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:55, 1 ноября 2016 (MSK)&lt;br /&gt;
* п. 1.2 номера формул следует выравнивать по правому краю, а не прилеплять вплотную к формуле [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:54, 25 октября 2016 (MSK)&lt;br /&gt;
** Условно исправлено. Форматирование сделано негодными средствами, но неясно, установлены ли средства (https://en.wikipedia.org/wiki/Help:Displaying_a_formula#Equation_numbering), чтобы сделать правильно [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:55, 1 ноября 2016 (MSK)&lt;br /&gt;
*** Пробовал сделать указанными Вами средствами - на этом ресурсе указанные Вами шаблоны не заработали [[Участник:Yushin|Павел Юшин]]&lt;br /&gt;
* п. 1.3 состоит из одного предложения и не дает достаточно информации [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:54, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:55, 1 ноября 2016 (MSK)&lt;br /&gt;
* п. 1.7 приведенный рисунок не является информационным графом: не все дуги ориентированы, имеются циклы [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:54, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:55, 1 ноября 2016 (MSK)&lt;br /&gt;
* п. 1.9 не приведено оценки объема входных и выходных данных [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:54, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:55, 1 ноября 2016 (MSK)&lt;br /&gt;
* в разделе 2 отсутствуют необходимые пункты, п. 2.2 должен быть 2.7 [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:54, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:55, 1 ноября 2016 (MSK)&lt;br /&gt;
* В списке литературы 1 ссылка - скопированный шаблон без реальной ссылки, 2 ссылка - просто URL без выходных данных источника [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:54, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено частично. Ссылка 2 по-прежнему не имеет достаточных выходных данных [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:55, 1 ноября 2016 (MSK)&lt;br /&gt;
*** На сайте, где студентам выдавалось задание ( http://parallel.ru/ss16 ), данный материал предоставлялся в списке источников (номер [8]) в таком же виде, как он указан в данной статье [[Участник:Yushin|Павел Юшин]]&lt;br /&gt;
**** Не вижу никакого противоречия с тем, что я написал в замечании [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:47, 7 ноября 2016 (MSK)&lt;br /&gt;
**** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 16:34, 13 ноября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
* п. 2.4. Приведен график зависимости эффективности от параметров задачи. Не указано, о какой конкретно эффективности идет речь. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:29, 17 ноября 2016 (MSK)&lt;br /&gt;
** Была ссылка в справочный раздел с описанием эффективности&lt;br /&gt;
** Подпись под рисункам должна быть самодостаточна, без необходимости разбираться, куда была ссылка и какую ссылку искать. То же касается текста: он должен быть понятен без необходимости ходить по ссылкам, ссылки - средство предоставить дополнительную информацию, для уточнения деталей. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 16:31, 18 ноября 2016 (MSK)&lt;/div&gt;</summary>
		<author><name>Coctic</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:%D0%AF%D0%BD-%D0%9C%D0%B0%D1%80%D1%82%D0%B8%D0%BD_%D0%A2%D0%B0%D0%BC%D0%BC/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%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=18106</id>
		<title>Участник:Ян-Мартин Тамм/Строгий алгоритм С средних</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:%D0%AF%D0%BD-%D0%9C%D0%B0%D1%80%D1%82%D0%B8%D0%BD_%D0%A2%D0%B0%D0%BC%D0%BC/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%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=18106"/>
		<updated>2016-11-18T11:15:57Z</updated>

		<summary type="html">&lt;p&gt;Coctic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Строгий алгоритм С средних (K-means, Hard C-Means)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(nkdi)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(log_2(k)log_2(d)i)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(nkd)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;nd+1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;nk&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
Автор: [[Участник:Darel|Ян-Мартин Тамм]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритма =&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&amp;lt;b&amp;gt;Строгий алгоритм C средних&amp;lt;/b&amp;gt;, более известный как &amp;lt;b&amp;gt;K-средних&amp;lt;/b&amp;gt;, решает задачу разделения векторов в многомерном пространстве на заданное количество кластеров. При этом каждый вектор принадлежит только одному кластеру, поэтому алгоритм называется строгим, в то время как нечеткий алгоритм C средних (Fuzzy C-means, Soft K-means) определяет степень принадлежности вектора каждому из кластеров.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Данная задача является NP-трудной, тем не менее описываемый алгоритм сходится к локальному оптимуму. Глобальный оптимум не гарантируется и зависит от первоначального распределения центров кластеров и их количества. &amp;lt;br&amp;gt;Общая идея алгоритма такова: фиксируем число кластеров &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;, произвольным образом выбираем центры кластеров, после чего повторяем следующие два действия, пока не будет выполнено условие остановки:&lt;br /&gt;
#Распределяем каждый вектор в ближайший кластер&lt;br /&gt;
#Пересчитываем значения центров как среднее значение координат векторов в каждом кластере&lt;br /&gt;
Минимизируется сумма расстояний векторов от центров их кластеров. Остановка производится если либо значение данной функции становится ниже некоторого порога, либо мало изменяется по сравнению с предыдущей итерацией.&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Дано множество d-мерных векторов &amp;amp;nbsp;&amp;lt;math&amp;gt;U=\{u_1, u_2, ..., u_n\}&amp;lt;/math&amp;gt; и число кластеров &amp;lt;math&amp;gt;k \in \mathbb{N}&amp;lt;/math&amp;gt;. Требуется разбить множество &amp;lt;math&amp;gt;U&amp;lt;/math&amp;gt; на &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; непересекающихся непустых кластеров &amp;lt;math&amp;gt;C_1, C_2, ..., C_k&amp;lt;/math&amp;gt; таких, что &amp;lt;math&amp;gt;{\bigcup \limits _{i = 1}^k C_i} = U &amp;lt;/math&amp;gt;. &lt;br /&gt;
&amp;lt;br&amp;gt;Для этого минимизируется функция &amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^k J_i = \sum\limits_{i=1}^k \sum\limits_{ u \in C_i} \|u-c_i \|^2 &lt;br /&gt;
&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;c_i&amp;lt;/math&amp;gt;— центр масс векторов кластера &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Произвольным образом инициализируем центры кластеров &amp;lt;math&amp;gt;c_1, c_2, ..., c_k&amp;lt;/math&amp;gt;, после чего начинается основная часть алгоритма.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&amp;lt;li&amp;gt;Каждый вектор &amp;lt;math&amp;gt;u_l&amp;lt;/math&amp;gt; определяем в ближайший к нему кластер &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt;, то есть такой, что &lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\|u_l-c_i\|^2 \leqslant \|u_l-c_j\|^2 \;\; \forall i \neq j; \;\; (i,j=1,2,\ldots,k, \; l = 1,2,\ldots,n)&lt;br /&gt;
&amp;lt;/math&amp;gt;.&amp;lt;/li&amp;gt; Хранить информацию о принадлежности векторов кластерам будем в матрице &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; следующего вида:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ij} = \begin{cases}&lt;br /&gt;
1, &amp;amp; u_j \in C_i \\&lt;br /&gt;
0, &amp;amp; \text{otherwise}&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Считаем значение функции &amp;lt;math&amp;gt;J&amp;lt;/math&amp;gt; и прекращаем работу алгоритма, если это значение меньше заданного порога &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;, либо значение мало изменилось после текущей итерации.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Обновляем значения центров кластеров&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{u \in C_i} u \;\; (i=1,2,\ldots,k)&lt;br /&gt;
&amp;lt;/math&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Возвращаемся к распределению векторов по кластерам.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительным ядром алгоритма является весь алгоритм, а именно два основных его шага:&lt;br /&gt;
&amp;lt;ul&amp;gt;&amp;lt;li&amp;gt;Распределение векторов по кластерам&amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;Пересчёт центров кластеров&amp;lt;/li&amp;gt;&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как уже говорилось раньше, первоначальное распределение векторов по кластерам может быть произвольным, например, можно случайным образом выбрать &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; векторов из множества всех векторов &amp;lt;math&amp;gt;U&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Далее начинается цикл, его первая операция — распределение векторов по кластерам. В ней для каждого вектора считается расстояние от него, до каждого кластера &amp;lt;math&amp;gt;\rho = \big \| u - c \big \|^2=\sum_{i=1}^d (u_i-c_i)^2&amp;lt;/math&amp;gt;, после чего из них выбирается наименьшее и заносится в матрицу.&amp;lt;br&amp;gt;Подсчёт функции &amp;lt;math&amp;gt;J&amp;lt;/math&amp;gt; можно проводить одновременно с первым шагом, так как в ней суммируются те же самые расстояния.&amp;lt;br&amp;gt;Пересчёт центров кластеров — сумма всех векторов кластера, делённая на количество объектов в кластере. &amp;lt;math&amp;gt;&lt;br /&gt;
c = \frac{1}{|C|} \sum\limits_{u \in C} u&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def kmeans(points, k, cutoff):&lt;br /&gt;
    &lt;br /&gt;
    # Pick out k random points to use as our initial centroids&lt;br /&gt;
    initial = random.sample(points, k)&lt;br /&gt;
    &lt;br /&gt;
    # Create k clusters using those centroids&lt;br /&gt;
    clusters = [Cluster([p]) for p in initial]&lt;br /&gt;
    &lt;br /&gt;
    # Loop through the dataset until the clusters stabilize&lt;br /&gt;
    while True:&lt;br /&gt;
        # Create a list of lists to hold the points in each cluster&lt;br /&gt;
        lists = [ [] for c in clusters]&lt;br /&gt;
&lt;br /&gt;
        # For every point in the dataset ...&lt;br /&gt;
        for p in points:&lt;br /&gt;
            # Get the distance between that point and the centroid of the first cluster.&lt;br /&gt;
            smallest_distance = getDistance(p, clusters[0].centroid)&lt;br /&gt;
        &lt;br /&gt;
            # Set the cluster this point belongs to&lt;br /&gt;
            clusterIndex = 0&lt;br /&gt;
        &lt;br /&gt;
            # For the remainder of the clusters ...&lt;br /&gt;
            for i in range(clusterCount - 1):&lt;br /&gt;
                # calculate the distance of that point to each other cluster&#039;s centroid&lt;br /&gt;
                distance = getDistance(p, clusters[i+1].centroid)&lt;br /&gt;
                # If it&#039;s closer to that cluster&#039;s centroid update what we&lt;br /&gt;
                # think the smallest distance is, and set the point to belong to that cluster&lt;br /&gt;
                if distance &amp;lt; smallest_distance:&lt;br /&gt;
                    smallest_distance = distance&lt;br /&gt;
                    clusterIndex = i+1&lt;br /&gt;
            lists[clusterIndex].append(p)&lt;br /&gt;
        &lt;br /&gt;
        # Set our total_shift to zero for this iteration&lt;br /&gt;
        total_shift = 0.0&lt;br /&gt;
        &lt;br /&gt;
        # As many times as there are clusters ...&lt;br /&gt;
        for i in range(k):&lt;br /&gt;
            # Calculate how far the centroid moved in this iteration&lt;br /&gt;
            shift = clusters[i].update(lists[i])&lt;br /&gt;
            # Keep track of the total moves from all cluster centroid updates&lt;br /&gt;
            total_shift += shift&lt;br /&gt;
        &lt;br /&gt;
        # If the centroids have stopped moving much, we&#039;re done!&lt;br /&gt;
        if total_shift &amp;lt; cutoff:&lt;br /&gt;
            break&lt;br /&gt;
    return clusters&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Распределение по кластерам — для каждого из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов и каждого из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; кластеров посчитать расстояние, сложив &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; раз значения, на вычисление каждого из которых нужно 2 операции —&amp;amp;nbsp;&amp;lt;math&amp;gt;O(nkd)&amp;lt;/math&amp;gt;. Пересчёт центров — &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; раз сложить и &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; раз поделить — &amp;amp;nbsp;&amp;lt;math&amp;gt;O(n+k)&amp;lt;/math&amp;gt;. На завершение алгоритма понадобится &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; итераций. Итого сложность &amp;lt;math&amp;gt;O(nkdi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
На рисунке ниже приведён информационный граф алгоритма.&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:HCM graph1.png]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Блок, определяющий ближайший кластер, подробнее.&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:HCM_dist1.png]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Самой трудоёмкой операцией является распределение по кластерам. Так, для рассчёта расстояний, можно провести суммирование &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; элементов за &amp;lt;math&amp;gt;log_2(d)&amp;lt;/math&amp;gt; операций. Расстояние от данного вектора до всех кластеров можно найти за одну операцию, после чего нужно найти наименьшее значение из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; элементов за &amp;lt;math&amp;gt;log_2(k)&amp;lt;/math&amp;gt; операций. И всё это нужно сделать для &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов, что можно сделать параллельно за одну операцию. Для сходимости всё так же потребуется &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; итераций, общая сложность получается &amp;lt;math&amp;gt;O(log_2(k)log_2(d)i)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; &lt;br /&gt;
*&amp;lt;math&amp;gt;U=\{u_1, u_2, ..., u_n\} \subset \mathbb{R}^d&amp;lt;/math&amp;gt; — множество векторов&lt;br /&gt;
*&amp;lt;math&amp;gt;k \in \mathbb{N}&amp;lt;/math&amp;gt; — количество кластеров&lt;br /&gt;
*&amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; — порог остановки &#039;&#039;(не обязательно)&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;nd+1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
*&amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; — матрица принадлежности векторов кластерам размера &amp;lt;math&amp;gt;nk&amp;lt;/math&amp;gt;. При этом данная матрица содержит только &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; единиц, остальные значения ноль. Возможен вывод в другом виде, например, список списков.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;nk&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&amp;lt;ul&amp;gt;&amp;lt;li&amp;gt;Алгоритм не является детерминированным, так как инициализация кластеров происходит случайным образом, однако, ничто не мешает проводить инициализацию согласно некоторому детерминированному правилу.&lt;br /&gt;
&amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;Алгоритм находит локальный оптимум, поэтому его обычно запускают несколько раз и выбирают лучший результат.&amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;Вычислительная мощность &amp;lt;math&amp;gt;\frac{kdi}{k+d}&amp;lt;/math&amp;gt;&amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;Алгоритм является устойчивым при одинаковой первоначальной инициализации — малая ошибка в начальных данных или при вычислениях очень незначительно повлияют на результат (скорее всего никак не повлияют). Тем не менее, при случайной инициализации результаты будут различны.&amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;Прост в реализации и вычислениях&amp;lt;/li&amp;gt;&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Для масштабируемости использовалась следующая [http://users.eecs.northwestern.edu/~wkliao/Kmeans/index.html параллельная реализация алгоритма] с использованием MPI. Тесты были проведены на компьютерной системе [http://hpc.cmc.msu.ru/bgp BlueGene], которая включает в себя 8192 процессорных ядра и имеет пиковую производительность 27.9 терафлопс.&lt;br /&gt;
&lt;br /&gt;
Исследовалась сильная масштабируемость алгоритма. На графике видно, что алгоритм хорошо распараллеливается и достигается значительное ускорение. Рассчитывалось распределение десятимерных векторов на десять кластеров.&lt;br /&gt;
[[Файл:HCM_BlueGene.png]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
* [http://scikit-learn.org/ scikit-learn] библиотека машинного обучения для языка Python.&lt;br /&gt;
* [https://www.scipy.org/ SciPy] библиотека на языке Python, содержащая большое число реализаций различных алгоритмов.&lt;br /&gt;
* [http://elki.dbs.ifi.lmu.de ELKI] библиотека для анализа данных на языке программирования Java, содержит различные алгоритмы кластеризации.&lt;br /&gt;
* [http://spark.apache.org/ Spark] распределённая версия алгоритма.&lt;br /&gt;
* [http://mlpack.org MLPACK] библиотека машинного обучения для C++.&lt;br /&gt;
* [http://opencv.org/ OpenCV] библиотека содержит реализацию алгоритма.&lt;br /&gt;
* [http://mahout.apache.org Apache Mahout] содержит реализацию алгоритма на базе MapReduce.&lt;br /&gt;
* [http://www.cs.waikato.ac.nz/~ml/weka Weka] библиотека и инструмент для анализа данных на языке Java.&lt;br /&gt;
* [http://torch.ch/ Torch] библиотека машинного обучения на базе языка программирования Lua.&lt;br /&gt;
* [http://www.accord-framework.net/ Accord.NET] содержит несколько различных реализаций на языке C#.&lt;br /&gt;
* [https://www.r-bloggers.com/k-means-clustering-in-r/ R k-means] реализация на языке R.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&amp;lt;ol&amp;gt;&amp;lt;li&amp;gt;[http://faculty.petra.ac.id/resmana/private/fuzzy/nfmod.pdf Jan Jantzen «Neurofuzzy Modelling».(Электронное издание)] Technical University of Denmark, Department of Automation, Bldg 326, DK-2800 Lyngby, DENMARK.&lt;br /&gt;
Tech. report no 98-H-874 (nfmod), 30 Oct 1998. &amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;Steinhaus H. (1956). Sur la division des corps materiels en parties. Bull. Acad. Polon. Sci., C1. III vol IV: 801—804.&amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;Lloyd S. (1957). Least square quantization in PCM’s. Bell Telephone Laboratories Paper.&amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;MacQueen J. (1967). Some methods for classification and analysis of multivariate observations. In Proc. 5th Berkeley Symp. on Math. Statistics and Probability, pages 281—297.&amp;lt;/li&amp;gt;&amp;lt;/ol&amp;gt;&lt;/div&gt;</summary>
		<author><name>Coctic</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Darel&amp;diff=18105</id>
		<title>Обсуждение участника:Darel</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Darel&amp;diff=18105"/>
		<updated>2016-11-18T11:15:42Z</updated>

		<summary type="html">&lt;p&gt;Coctic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Статья [[Участник:Ян-Мартин Тамм/Строгий алгоритм С средних]] =&lt;br /&gt;
* Отсутствует указание автора [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:17, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:58, 31 октября 2016 (MSK)&lt;br /&gt;
* Пропущен пункт 1.1 &amp;quot;общее описание алгоритма&amp;quot;, у следующих пунктов сместилась нумерация [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:17, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:58, 31 октября 2016 (MSK)&lt;br /&gt;
* п. 1.6 на рисунках приведены схема алгоритма и его блока, информационного графа не приведено [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:17, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:58, 31 октября 2016 (MSK)&lt;br /&gt;
----------------------&lt;br /&gt;
* Названия частей 1 и 2 не соответствуют шаблону [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:58, 31 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:02, 8 ноября 2016 (MSK)&lt;br /&gt;
* В списке литературы у первой ссылки отсутствуют выходные данные, по которым можно однозначно идентифицировать источник [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:17, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:02, 8 ноября 2016 (MSK)&lt;br /&gt;
* Отсутствует п. 2.4. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 16:55, 16 ноября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 14:15, 18 ноября 2016 (MSK)&lt;br /&gt;
* П. 2.4. Необходимо добавить описание ключей компилятора, особенностей запуска (раздел, используемые вычислительные узлы и т.п. информация, достаточная для воспроизведения данных). [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 14:15, 18 ноября 2016 (MSK)&lt;/div&gt;</summary>
		<author><name>Coctic</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:Nikmedoed/%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_(Fuzzy_C-means)&amp;diff=18073</id>
		<title>Участник:Nikmedoed/Нечеткий алгоритм С-средних (Fuzzy C-means)</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:Nikmedoed/%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_(Fuzzy_C-means)&amp;diff=18073"/>
		<updated>2016-11-18T09:41:34Z</updated>

		<summary type="html">&lt;p&gt;Coctic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм С-средних (Fuzzy C-means)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(c^2 MI + cMnI), (I&amp;lt;/math&amp;gt; - число итераций, &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - число точек, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - размерность точек (свойств на объект)&amp;lt;math&amp;gt;)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;Mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;cM&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt; O(c^2 I + cnI)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O( M )&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы: [[Участник:Nikmedoed|Н.А. Муромцев]] - перенос в вики, раздел 2, картинки, [[Участник:illusive_mike|М.С. Дворецкий]] - раздел 1&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Нечеткий алгоритм С-средних&#039;&#039;&#039; (&#039;&#039;Fuzzy C-means&#039;&#039;) - позволяет получить нечёткую кластеризацию больших наборов числовых данных, что позволяет корректно определять объекты на границах кластеров. Однако, выполнение данного алгоритма требует серьёзных вычислительных ресурсов, а также изначального задания количества кластеров. Кроме того, может возникнуть неоднозначность с объектами, удалёнными от центров всех кластеров.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Алгоритм кластеризации Fuzzy C-Means (FCM) был предложен Дж. Данном в 1973 году &amp;lt;ref&amp;gt;Dunn, J.C.: A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters. Journal of Cybernetics. 3 (1973): 32–57&amp;lt;/ref&amp;gt; и доработан Дж. Бездеком в 1981 году &amp;lt;ref&amp;gt;Bezdek, J.C.: Pattern Recognition with Fuzzy Objective Function Algorithms. Plenum Press, New York (1981). ISBN 0-306-40671-3&amp;lt;/ref&amp;gt;. В отличие от большинства существующих алгоритмов кластеризации, данный алгоритм является нечётким – каждый из объектов не входит однозначно в какой-либо кластер, а принадлежит всем кластерам с различными степенями принадлежности. Это даёт преимущества в качестве разбиения в случаях, когда кластеры находятся близко друг к другу, и большое число точек находится на их границах. Однако ценой такой нечёткости служат большие вычислительные затраты, чем у таких чётких алгоритмов, как [[Hard C-Means]] и [[K-Means]], при сохранении таких их недостатков, как априорное определение числа кластеров и отсутствие гарантии глобальной оптимальности результата.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Исходные данные: массив объектов &amp;lt;math&amp;gt;{X_k}\in{\R^n}, k=\overline{1,M}&amp;lt;/math&amp;gt;, число кластеров c, экспоненциальный вес &amp;lt;math&amp;gt;m\in{[1,\infty)}&amp;lt;/math&amp;gt;, параметр останова &amp;lt;math&amp;gt;\varepsilon&amp;gt;0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные: матрица разбиения &amp;lt;math&amp;gt;F&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;M\times c&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;\mu_{ki}\in[0,1]&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\sum^{c}_{i=1} {\mu_{ki}} = 1&amp;lt;/math&amp;gt;), центры кластеров &amp;lt;math&amp;gt;V_i&amp;lt;/math&amp;gt;, расстояния &amp;lt;math&amp;gt;D_{ki}&amp;lt;/math&amp;gt; между объектами и центрами кластеров.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Формулы метода (вычисляются последовательно на каждой итерации):&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
1. Уточнение центров кластеров по степеням принадлежности&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
&amp;amp;V_i=\frac{\sum^{M}_{k=1} {\mu^m_{ki} * X_k}}{\sum^{M}_{k=1} {\mu^m_{ki}}},i=\overline{1,c}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
2. Расчёт расстояний между новыми центрами кластеров и точками данных&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
&amp;amp;D_{ki}=\sqrt{{\lVert X_k - V_i \rVert}^2},k=\overline{1,M},i=\overline{1,c}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
3. Пересчёт степеней принадлежности объектов кластерам&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
&amp;amp;\mu_{ki}=\frac{1}{{ \sum^{c}_{j=1} \left ( {\frac{D_{ki}}{D_{kj}}} \right ) }^{{2}/{m-1}}&lt;br /&gt;
},k=\overline{1,M},i=\overline{1,c}\\&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На каждой итерации алгоритма происходит уточнение элементов матрицы &amp;lt;math&amp;gt;F&amp;lt;/math&amp;gt;. Выходом алгоритма служит матрица &amp;lt;math&amp;gt;F&amp;lt;/math&amp;gt;, к которой алгоритм сходится. Факт того, что алгоритм сошёлся, устанавливается проверкой вида &amp;lt;math&amp;gt;\max_{k = \overline{1,M},i = \overline{1,c}} {( \left | \mu_{ki} - \mu_{ki}^* \right |)} &amp;lt; \varepsilon&amp;lt;/math&amp;gt;  либо  &amp;lt;math&amp;gt;\max_{i = \overline{1,c}} {( \left | V_i - V_i^* \right |)} &amp;lt; \varepsilon&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\mu_{ki}^* (V_i^*)&amp;lt;/math&amp;gt; – значение &amp;lt;math&amp;gt;\mu_{ki}(V_i)&amp;lt;/math&amp;gt;, вычисленное на предыдущей итерации.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро алгоритма Fuzzy C-Means составляют шаги вычисления центров кластеров, расстояний между ними и точками данных и в особенности пересчёта матрицы степеней принадлежности точек данных.&lt;br /&gt;
&lt;br /&gt;
При реальном вычислении некоторые повторяющиеся вычисления могут быть устранены. Так, для шага вычисления центров кластеров величины &amp;lt;math&amp;gt;\mu_{ki}^m&amp;lt;/math&amp;gt; могут вычисляться однократно и умножаться на &amp;lt;math&amp;gt;X_k&amp;lt;/math&amp;gt; при включении в сумму, записанную в числителе. Для шага вычисления расстояний между центрами кластеров и точками, операция взятия квадратного корня не является обязательной, так как в дальнейшем на шаге вычисления степеней принадлежности можно непосредственно использовать квадраты этих расстояний, и сумма в знаменателе будет приобретать вид:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum^{c}_{j=1} {\left ( \frac{D_{ki} ^ {2}}{D_{kj} ^ {2}} \right )}^{{1}/{m-1}}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Алгоритм включает в себя три основных этапа – вычисление центров кластеров, вычисление расстояний между центрами кластеров и точками данных (включающее в себя макрооперации вычитания векторов и вычисления их норм, как правило в Евклидовом пространстве) и пересчёт матрицы принадлежности.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Последовательность исполнения алгоритма следующая:&lt;br /&gt;
&lt;br /&gt;
Инициализация происходит случайным заполнением матрицы принадлежности &amp;lt;math&amp;gt;F&amp;lt;/math&amp;gt; с соблюдением условия нормировки &amp;lt;math&amp;gt;\sum_{i=1}^c {\mu_{ki} =1}&amp;lt;/math&amp;gt; и переходом к шагу 1, либо случайным определением центров кластеров &amp;lt;math&amp;gt;V_i&amp;lt;/math&amp;gt; и переходом к шагу 2.&lt;br /&gt;
&lt;br /&gt;
Далее осуществляются итерации следующего вида:&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;math&amp;gt;V_i=\frac{\sum_{k=1}^{M} {\mu_{ki}^m * X_k}}{\sum_{k=1}^{M} {\mu_{ki}^m} },i=\overline{1,c}&amp;lt;/math&amp;gt;&lt;br /&gt;
# &amp;lt;math&amp;gt;D_{ki}=\sqrt{{\lVert X_k - V_i \rVert}^2},k=\overline{1,M},i=\overline{1,c}&amp;lt;/math&amp;gt;&lt;br /&gt;
# &amp;lt;math&amp;gt;\mu_{ki}=\frac{1}{{ \sum^{c}_{j=1} {\left ( \frac{D_{ki}}{D_{kj}} \right )} }^{{2}/{m-1}}&lt;br /&gt;
},k=\overline{1,M},i=\overline{1,c}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В конце каждой итерации проверяется условие останова вида &amp;lt;math&amp;gt;\max_{k = \overline{1,M},i = \overline{1,c}} {( \left | \mu_{ki} - \mu_{ki}^* \right |)} &amp;lt; \varepsilon&amp;lt;/math&amp;gt;, либо &amp;lt;math&amp;gt;\max_{i = \overline{1,c}} {( \left | V_i - V_i^* \right |)} &amp;lt; \varepsilon&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\mu_{ki}^* (V_i^*)&amp;lt;/math&amp;gt; – значение &amp;lt;math&amp;gt;\mu_{ki}(V_i)&amp;lt;/math&amp;gt;, вычисленное на предыдущей итерации. Если условие не выполнено, осуществляется переход к шагу 1.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
При кластеризации &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; объектов данных, представленных точками в &amp;lt;math&amp;gt;\R^n&amp;lt;/math&amp;gt;, на &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; кластеров, алгоритм Fuzzy C-Means в последовательном варианте имеет вычислительную сложность – &amp;lt;math&amp;gt;O(c^2 MI+cMnI)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;I&amp;lt;/math&amp;gt; – число итераций. Если считать размерность данных &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; малой, то эта сложность сводится к &amp;lt;math&amp;gt;O(c^2 MI)&amp;lt;/math&amp;gt;. Основной частью алгоритма в этом случае является пересчёт матрицы принадлежностей, требующий вычисления &amp;lt;math&amp;gt;cM&amp;lt;/math&amp;gt; сумм из &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; слагаемых на каждой итерации.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
Приведём граф единичной итерации алгоритма в параллельном оптимизированном варианте (метод распараллеливания взят в &amp;lt;ref&amp;gt;Kwok, T., Smith, K.,&lt;br /&gt;
Lozano, S., Taniar, D.: [http://num-meth.srcc.msu.ru/zhurnal/tom_2012/pdf/v13r207.pdf Parallel Fuzzy c-Means Clustering for Large Data Sets], последнее обращение 25.10.2016&amp;lt;/ref&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
[[File:C-means_paralle_graph.png|thumb|upright=2.5|frame|center|alt=Paralel Fuzzy C-Means|Каждая вершина данного графа соответствует операциям из алгоритма, указанным при помощи указанных формул. Каждый из p столбцов соответствует работе одного из процессов. Пометки справа указывают число повторений каждого узла в ходе одной итерации.]]&lt;br /&gt;
&lt;br /&gt;
Раздел 1.8 уточняет, соответствуют ли эти повторения однотипным ярусам или точкам данных, вычисления для которых можно распараллелить и далее.&lt;br /&gt;
&lt;br /&gt;
Каждый процесс обладает следующими данными:&lt;br /&gt;
* координатами точек данных &amp;lt;math&amp;gt;X_k&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;k=\overline{1+rnk* \frac{M}{p},rnk*(\frac{M}{p}+1)}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;rnk&amp;lt;/math&amp;gt; – номер процесса,&lt;br /&gt;
* значениями &amp;lt;math&amp;gt;\mu_{ki}&amp;lt;/math&amp;gt; степени принадлежности для своих точек (&amp;lt;math&amp;gt;k=\overline{1+rnk* \frac{M}{p},rnk*(\frac{M}{p} +1)}, i=\overline{1,c}&amp;lt;/math&amp;gt;),&lt;br /&gt;
* координатами центров кластеров &amp;lt;math&amp;gt;V_i&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;i=\overline{1,c}&amp;lt;/math&amp;gt;.&lt;br /&gt;
Суммы &amp;lt;math&amp;gt;\sum_{k=1+rnk*\frac{M}{p}}^{rnk * ( \frac{M}{p} +1 )} {\mu_{ki}^m}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\sum_{k=1+rnk*\frac{M}{p}}^{rnk * ( \frac{M}{p} +1 )} {\mu_{ki}^m X_k}&amp;lt;/math&amp;gt; вычисляются одновременно, поэтому значения &amp;lt;math&amp;gt;\mu_{ki}^m&amp;lt;/math&amp;gt; вычисляются по одному разу за итерацию. Таким образом, второй ярус операций на рисунке на деле не содержит операций возведения в степень.&lt;br /&gt;
За счёт линейности большинства выражений относительно данных по точкам, процессы взаимодействуют только при редукции сумм, составляющих &amp;lt;math&amp;gt;V_i&amp;lt;/math&amp;gt;. Всё остальное время каждый процессор работает только со своими &amp;lt;math&amp;gt;\frac{M}{p}&amp;lt;/math&amp;gt; точками. Это обеспечивает применимость алгоритма для больших &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
При распараллеливании по точкам исходных данных и условии останову по малому изменению степеней принадлежности выполнение одной итерации алгоритма FCM может быть разделено на следующие ярусы:&lt;br /&gt;
* &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; ярусов нахождения частичных сумм знаменателя (по &amp;lt;math&amp;gt;\frac{M}{p}-1&amp;lt;/math&amp;gt; сложений, &amp;lt;math&amp;gt;\frac{M}{p}&amp;lt;/math&amp;gt; операций возведения в степень на процесс),&lt;br /&gt;
* &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; ярусов нахождения частичных сумм числителя (по &amp;lt;math&amp;gt;\frac{M}{p} -1&amp;lt;/math&amp;gt; сложений, &amp;lt;math&amp;gt;\frac{M}{p}&amp;lt;/math&amp;gt; умножений на процесс),&lt;br /&gt;
* &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; редукции сумм и передач значений &amp;lt;math&amp;gt;V_i&amp;lt;/math&amp;gt; процессам (получение &amp;lt;math&amp;gt;c(n+1)&amp;lt;/math&amp;gt; значений, &amp;lt;math&amp;gt;cn&amp;lt;/math&amp;gt; делений),&lt;br /&gt;
* &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; ярусов вычисления расстояний до центров (по &amp;lt;math&amp;gt;n-1&amp;lt;/math&amp;gt; сложений, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; вычитаний, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений), каждый процесс получает &amp;lt;math&amp;gt;\frac{M}{p}&amp;lt;/math&amp;gt; точек на обработку,&lt;br /&gt;
* &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; ярусов вычисления степеней принадлежности точек (по &amp;lt;math&amp;gt;c+1&amp;lt;/math&amp;gt; делений, c возведений в степень, &amp;lt;math&amp;gt;c-1&amp;lt;/math&amp;gt; сложений), каждый процесс получает &amp;lt;math&amp;gt;\frac{M}{p}&amp;lt;/math&amp;gt; точек на обработку,&lt;br /&gt;
* до &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; ярусов проверки условий останова (по &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; вычитанию, &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; сравнению), каждый процесс получает &amp;lt;math&amp;gt;\frac{M}{p}&amp;lt;/math&amp;gt; точек на обработку,&lt;br /&gt;
* &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; редукция для обмена статусом завершения.&lt;br /&gt;
Таким образом, при распараллеливании по точкам исходных данных при условии наличия в каждом узле достаточного объёма памяти для хранения всего массива координат центров кластеров высота и ширина ЯПФ алгоритма FCM равны соответственно &amp;lt;math&amp;gt;O(c^2 I+cnI)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;O(M)&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;X_i&amp;lt;/math&amp;gt;, число кластеров &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;, экспоненциальный вес &amp;lt;math&amp;gt;m\in{[1,\infty)}&amp;lt;/math&amp;gt;, параметр останова &amp;lt;math&amp;gt;\varepsilon&amp;gt;0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;Mn&amp;lt;/math&amp;gt; для входных векторов, 3 вспомогательных параметра.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица принадлежности &amp;lt;math&amp;gt;F&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;\mu_{ki}\in[0,1]&amp;lt;/math&amp;gt;). Условие нормировки: &amp;lt;math&amp;gt;\sum^{c}_{i=1} {\mu_{ki}} = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;cM&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
В случае неограниченного распараллеливания по точкам данных (1 процесс на точку), отношение последовательной сложности алгоритма к параллельной пропорционально &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Параметр &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; задаёт степень «размытости» кластеров. В отсутствие априорных данных его обычно берут равным 2. В предельном случае сведения параметра &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; к значению 1, кластеры становятся чёткими и алгоритм вырождается в алгоритм кластеризации K-Means.&lt;br /&gt;
&lt;br /&gt;
Алгоритм недетерминирован, начальное положение кластеров задаётся случайно либо явно, либо опосредованно (через матрицу принадлежности). Алгоритм сходится к локальному экстремуму &amp;lt;ref&amp;gt;Höppner, F., Klawonn, F.: [https://public.fh wolfenbuettel.de/~klawonn/Papers/hoeppnerklawonntfs03.pdf A Contribution to Convergence Theory of Fuzzy c-Means and Derivatives], Дата последнего обращения: 13.10.2016&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;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
[[File:График.png|thumb|upright=2.5|frame|right|alt=Paralel Fuzzy C-Means time to iteration|График зависимости времени выполнения итерации параллельного нечеткого алгоритма С-средних (Fuzzy C-means) от количества процессоров и количества кластеризуемых вершин]]&lt;br /&gt;
&lt;br /&gt;
[[File:Effect_parallel_fuzzy_c-means.png|thumb|upright=2.5|frame|right|alt=Paralel Fuzzy C-Means efficiency|График временной эффективности параллельного нечеткого алгоритма С-средних (Fuzzy C-means) в зависимости от количества процессоров и количества кластеризуемых вершин.]]&lt;br /&gt;
&lt;br /&gt;
Исследование проведено на суперкомпьютере IBM Blue Gene/P&amp;lt;ref&amp;gt;[http://hpc.cs.msu.ru/bgp Описание вычислительного комплекса IBM Blue Gene/P]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
Для исследования была использована последовательная реализация алгоритма и реализован её [https://github.com/nikmedoed/Parallel-Fuzzy-C-means параллельный вариант]&amp;lt;ref&amp;gt;[https://github.com/nikmedoed/Parallel-Fuzzy-C-means Параллельная реализация алгоритма Fuzzy C-Means]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
Алгоритм обладает плохо исследованной сходимостью, но объем вычислений и итераций не зависит от значений данных, поэтому данное исследование масштабируемости было произведено для единичной итерации.&lt;br /&gt;
&lt;br /&gt;
Для упрощения экспериментов было решено использовать количество вершин для кластеризации и количество процессов равное степени двойки, поэтому для каждого эксперимента были выбраны значения:&lt;br /&gt;
* &amp;lt;math&amp;gt;2^v, v=\overline{0,9}&amp;lt;/math&amp;gt;, для количества процессоров;&lt;br /&gt;
* &amp;lt;math&amp;gt;2^w, w=\overline{10,20}&amp;lt;/math&amp;gt;, для количества кластеризуемых вершин.&lt;br /&gt;
&lt;br /&gt;
Для одного набора значений проводилось 4 эксперимента и результаты усреднялись. При повторных запусках экспериментов значения выходили те же самые.&lt;br /&gt;
&lt;br /&gt;
Полученные результаты говорят о хорошей масштабируемости реализации алгоритма. Для большинства экспериментов эффективность находится в пределах 100±3%. Высокая эффективность обуславливается тем, что данные равномерно распределены по процессорам и на каждой итерации требуется глобальная редукция всего &amp;lt;math&amp;gt;2c+1&amp;lt;/math&amp;gt; значений (&amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; значений числителей центроид кластеров, &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; значений знаменателей центроид кластеров и одно значение признака останова). Таким образом вычисления занимают значительно больше времени, чем взаимодействия между процессами, которые практически не приводят к простоям из-за хорошей балансировки. Спад эффективности при малом числе вершин и большом числе процессоров обуславливается тем, что с уменьшением числа вершин, обрабатываемых каждым процессором, растёт доля времени обмена данных между процессорами, не зависящего от числа вершин, как показано выше.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
* пакет MATLAB &amp;lt;ref&amp;gt;[http://www.mathworks.com/help/fuzzy/fcm.html Документация пакета MATLAB, функция fcm], последнее обращение 15.10.2016&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Реализация алгоритма на POSTGRESQL &amp;lt;ref&amp;gt;[http://num-meth.srcc.msu.ru/zhurnal/tom_2012/pdf/v13r207.pdf Реализация алгоритма Fuzzy C-means на POSTGRESQL], последнее обращение 15.10.2016&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&lt;br /&gt;
[[en:Parallel Fuzzy c-Means Clustering]]&lt;/div&gt;</summary>
		<author><name>Coctic</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Nikmedoed&amp;diff=18072</id>
		<title>Обсуждение участника:Nikmedoed</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Nikmedoed&amp;diff=18072"/>
		<updated>2016-11-18T09:41:23Z</updated>

		<summary type="html">&lt;p&gt;Coctic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Статья [[Участник:Nikmedoed/Нечеткий алгоритм С-средних (Fuzzy C-means)]] =&lt;br /&gt;
* не указан вклад каждого автора [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:01, 25 октября 2016 (MSK)&lt;br /&gt;
** Могли бы вы подсказать в каком формате это сделать? Просто общее сообщение, либо в каждом пункте указать?&lt;br /&gt;
*** В начале написать &amp;quot;Авторы: Автор1 - раздел 1, Автор2 - раздел 2&amp;quot;. Ну или что-то в том духе. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 18:01, 28 октября 2016 (MSK)&lt;br /&gt;
:::: Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:32, 31 октября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
* п. 1.2 приведен набор формул, однако отсутствует пояснения, как эти формулы складываются в алгоритм [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:01, 25 октября 2016 (MSK)&lt;br /&gt;
** П. 1.2 расширен в соответствии с замечанием. Ожидаю отзыв. [[Участник:Illusive_mike|Дворецкий М.С.]] ([[Обсуждение участника:Illusive_mike|обсуждение]]) 15:46, 25 октября 2016 (MSK)&lt;br /&gt;
::: Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:32, 31 октября 2016 (MSK)&lt;br /&gt;
----------------&lt;br /&gt;
* п. 2.4. проведены исследования масштабируемости одной итерации. Исследование масштабируемости реализации в целом отсутствует [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:27, 17 ноября 2016 (MSK)&lt;br /&gt;
** Добавлено в статью: &amp;quot;Алгоритм обладает плохо исследованной сходимостью, но объем вычислений и итераций не зависит от значений данных, поэтому данное исследование масштабируемости было произведено для единичной итерации.&amp;quot;&lt;br /&gt;
** Принято [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:41, 18 ноября 2016 (MSK)&lt;br /&gt;
* п. 2.4. Рис. 2 приведен график зависимости эффективности от параметров задачи. Не указано, о каком виде эффективности идет речь. Значение эффективности в 100% в реальности встречается очень редко, надо в тексте пояснить, почему такой хороший результат. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:27, 17 ноября 2016 (MSK)&lt;br /&gt;
** Добавили пояснение, что это график временной эффективности&lt;br /&gt;
** Что такое временная эффективность? В [[Глоссарий|глоссарии]] такой нет. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:41, 18 ноября 2016 (MSK)&lt;br /&gt;
** Добавили пояснение про причину высокой временной эффективности&lt;br /&gt;
* п. 2.4. &#039;&#039;Для большинства экспериментов эффективность находится в пределах 100±3%.&#039;&#039;. Как эффективность может быть больше 100%? [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:27, 17 ноября 2016 (MSK)&lt;br /&gt;
** Сверхлинейное ускорение&lt;br /&gt;
** [https://www.dropbox.com/s/2ijzr6g8mhrftts/%D0%B8%D1%82%D0%BE%D0%B3%D0%B8%20%D1%82%D0%B5%D1%81%D1%82%D0%B0.xlsx?dl=0 Ссылка на расчёты]&lt;br /&gt;
** Доступная нам система профилировки недостаточна, чтобы найти причину сверхлинейного ускорения точно, поэтому мы не упомянули её прямым текстом&lt;br /&gt;
** Сначала надо разобраться, какая эффективность имеется в виду. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:41, 18 ноября 2016 (MSK)&lt;/div&gt;</summary>
		<author><name>Coctic</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:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%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_(Hard_C-Means,_HCM)&amp;diff=17859</id>
		<title>Участник:Светлана Лукьяненко/Строгий алгоритм С средних (Hard C-Means, HCM)</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:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%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_(Hard_C-Means,_HCM)&amp;diff=17859"/>
		<updated>2016-11-17T07:38:10Z</updated>

		<summary type="html">&lt;p&gt;Coctic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Строгий алгоритм С средних (Hard C-Means,HCM)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;nN+1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;C(N+n)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Авторы описания: [[Участник:Светлана_Лукьяненко|Лукьяненко Светлана]](1.1, 1.3, 1.4, 1.8, 1.10, 2.4, 2.7), [[Участник:Юрий_Комаров|Комаров Юрий]](1.2, 1.5, 1.6, 1.7, 1.8, 1.9, 2.4)&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Строгий алгоритм C средних&#039;&#039;&#039; (&#039;&#039;&#039;&#039;&#039;Hard C-Means&#039;&#039;&#039;&#039;&#039;; &#039;&#039;Jang, Sun and Mizutani, 1997&#039;&#039;&amp;lt;ref&amp;gt;Jang, J.-S. R., Sun, C.-T. and Mizutani, E. (1997). Neuro-Fuzzy and Soft Computing, number&lt;br /&gt;
isbn 0-13-261066-3 in Matlab Curriculum Series, Prentice Hall, Upper Saddle River, NJ, USA.&amp;lt;/ref&amp;gt;) позволяет распределить большие наборы числовых данных по кластерам в многомерном пространстве&amp;lt;ref&amp;gt;Jan Jantzen (1998). [http://faculty.petra.ac.id/resmana/private/fuzzy/nfmod.pdf Neurofuzzy Modelling.]&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;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
==== Входные и выходные данные ====&lt;br /&gt;
На вход подаётся набор векторов &amp;lt;math&amp;gt;\{u_k\}_{k=1}^{N}&amp;lt;/math&amp;gt; пространства &amp;lt;math&amp;gt;\mathbb{R}^n&amp;lt;/math&amp;gt; и количество кластеров &amp;lt;math&amp;gt;C&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;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ij} = \begin{cases}&lt;br /&gt;
1, &amp;amp; u_j \in C_i, \\&lt;br /&gt;
0, &amp;amp; \text{otherwise},&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; подразумевается &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый построенный кластер, и набор &amp;lt;math&amp;gt;\{c_i\}_{i=1}^{C}&amp;lt;/math&amp;gt; центров этих кластеров.&lt;br /&gt;
&lt;br /&gt;
==== Описание алгоритма ====&lt;br /&gt;
Алгоритм состоит из 5 последовательных шагов.&amp;lt;ref&amp;gt;Нейский И. М. [http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf Классификация и сравнение методов кластеризации.] // Интеллектуальные технологии и системы. Сборник учебно-методических работ и статей аспирантов и студентов. – М.: НОК «CLAIM», 2006. – Выпуск 8. – С. 130-142.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 1&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация кластерных центров&#039;&#039;&#039; &amp;lt;math&amp;gt;c_i \, (i=1,2,\ldots,C)&amp;lt;/math&amp;gt; может происходить за счёт случайного выбора необходимого числа точек из входного набора либо путём явного указания.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 2&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вычисление рядовой матрицы&#039;&#039;&#039; &amp;lt;math&amp;gt;M = \|m_{ik}\|&amp;lt;/math&amp;gt;, элементы которой задаются следующими выражениями (&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; — количество элементов во входном наборе данных):&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ik} = \begin{cases}&lt;br /&gt;
1, &amp;amp; \|u_k-c_i\|^2 \leqslant \|u_k-c_j\|^2 \;\; \text{for all } i \neq j; \;\; (i,j=1,2,\ldots,C; \; k = 1,2,\ldots,N)\\&lt;br /&gt;
0, &amp;amp; \text{otherwise}.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;!-- При этом, как легко видеть, матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; обладает следующими свойствами:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\sum\limits_{i=1}^C m_{ij} = 1, \;\; \sum\limits_{i=1}^C\sum\limits_{j=1}^K m_{ij} = K.&lt;br /&gt;
&amp;lt;/math&amp;gt; --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Будем говорить, что &amp;lt;math&amp;gt;u_k \in C_i&amp;lt;/math&amp;gt;, если &amp;lt;math&amp;gt;m_{ik} = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 3&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Расчёт объектной функции:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^C J_i = \sum\limits_{i=1}^C \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right)&lt;br /&gt;
.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На этом шаге происходит &#039;&#039;&#039;&amp;lt;u&amp;gt;остановка и выход из цикла&amp;lt;/u&amp;gt;&#039;&#039;&#039;, если полученное значение ниже пороговой величины &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; или полученное значение не сильно отличается от значений, полученных на предыдущих циклах.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 4&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Пересчёт кластерных центров&#039;&#039;&#039; выполняется в соответствии со следующим уравнением:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;|C_i|&amp;lt;/math&amp;gt; подразумевается количество элементов в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом кластере.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 5&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Переход по циклу&#039;&#039;&#039; на шаг 2.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма составляют вычисления квадратов нормы расстояния от каждого из векторов исходной выборки до промежуточных кластерных центров &amp;lt;math&amp;gt;\|u_k-c_i\|^2&amp;lt;/math&amp;gt;. На каждой итерации алгоритма происходит расчёт &amp;lt;math&amp;gt;CN&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;&lt;br /&gt;
d_{ki} = \|u_k-c_i\|^2&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также на шаге вычисления объектной функции производится множественное суммирование полученных расстояний:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^C J_i = \sum\limits_{i=1}^C \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right),&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
а на шаге расчета кластерных центров происходит суммирование векторов:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Реализация последовательного алгоритма состоит в итеративном повторении блока, описанного далее в форме псевдокода, до тех пор, пока не будет достигнута желаемая точность.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;&lt;br /&gt;
J = 0;&lt;br /&gt;
M = zeros(N,C);&lt;br /&gt;
for i = 1 to N //go through every element&lt;br /&gt;
   d_min = MAXINT;&lt;br /&gt;
   j_min = 1;&lt;br /&gt;
   for j = 1 to C //deside which claster does element belong to&lt;br /&gt;
      d_ij  = sq_norm(u[i] - c[j]);&lt;br /&gt;
      if d_ij &amp;lt; d_min&lt;br /&gt;
         d_min = d_ij;&lt;br /&gt;
         j_min = j;&lt;br /&gt;
   //generation of output data&lt;br /&gt;
   J += d_min; &lt;br /&gt;
   M[i,j_min] = 1;&lt;br /&gt;
   c_new[j] += u[i];&lt;br /&gt;
   c_newCount[k]++;&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;NC&amp;lt;/math&amp;gt; операций вычисления квадрата нормы разности элементов;&lt;br /&gt;
* &amp;lt;math&amp;gt;NC&amp;lt;/math&amp;gt; операций сравнения (вычитаний);&lt;br /&gt;
* &amp;lt;math&amp;gt;3N&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
&lt;br /&gt;
Каждая операция вычисления нормы разности векторов предполагает выполнение &amp;lt;math&amp;gt;2n-1&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания и &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; операций возведения в квадрат (умножений), поэтому получаем для каждой итерации:&lt;br /&gt;
* &amp;lt;math&amp;gt;(2nC + 3)N&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания;&lt;br /&gt;
* &amp;lt;math&amp;gt;nNC&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
&lt;br /&gt;
Ожидая, что предельная точность будет достигнута менее, чем за &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; итераций (в противном случае применение алгоритма можно считать нецелесообразным), получаем итоговую сложность последовательной реализации алгоритма &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt; (в предположении, что &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; существенно меньше &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Приведём аналитическое и графическое описание графа алгоритма.&lt;br /&gt;
&lt;br /&gt;
Граф алгоритма состоит из 5 различных видов вершин.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первая&#039;&#039;&#039; группа вершин отмечена символом &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039;, ей соответствует вычисление минимального расстояния до кластерных центров, включающее в себя следующую последовательность действий:&lt;br /&gt;
* независимое вычисление расстояний от заданного элемента &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; до каждого из кластерных центров;&lt;br /&gt;
* последовательное сравнение полученных значений с целью отыскания минимума;&lt;br /&gt;
* передача найденного минимального расстояния и соответствующего ему индекса кластера.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вторая&#039;&#039;&#039; группа вершин отмечена символом &#039;&#039;&#039;&#039;&#039;M&#039;&#039;&#039;&#039;&#039;, ей соответствует операция записи единички в столбец, отвечающий текущей ветке графа, в позицию, полученную на предыдущем шаге и соответствующую ближайшему кластерному центру.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Третья&#039;&#039;&#039; вершина отмечена символом &#039;&#039;&#039;&#039;&#039;J&#039;&#039;&#039;&#039;&#039;, подразумевается, что на этом этапе происходит расчёт объектной функции.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Четвертая&#039;&#039;&#039; вершина обозначена треугольным маркером и помечена &#039;&#039;&#039;&#039;&#039;if&#039;&#039;&#039;&#039;&#039;, на этом этапе происходит проверка условия достижения необходимой точности (условия остановки итерационного процесса).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Пятая&#039;&#039;&#039; соответствует операции пересчёта кластерных центров, она отмечена как &#039;&#039;&#039;&#039;&#039;{c}&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Все эти виды вершин визуально выделены в одну большую группу, поскольку все вместе они составляют одну полную итерацию алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:HardCMeans1.png|thumb|800px|center|Рисунок 1. Информационный граф алгоритма. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (&amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; стартовых значений кластерных центров и 1 значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; на каждую вершину графа), &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039; — вычисление минимального расстояния до кластерных центров (подробнее см. рисунок 2), &#039;&#039;&#039;&#039;&#039;M&#039;&#039;&#039;&#039;&#039; — запись единички в соответствующий столбец матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, &#039;&#039;&#039;&#039;&#039;J&#039;&#039;&#039;&#039;&#039; — вычисление объектной функции по результатам полученных вычислений, &#039;&#039;&#039;&#039;&#039;if&#039;&#039;&#039;&#039;&#039; — проверка условия достижения заданной точности, &#039;&#039;&#039;&#039;&#039;{c}&#039;&#039;&#039;&#039;&#039; — пересчёт кластерных центров и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; значений полученных кластерных центров).]]&lt;br /&gt;
[[File:HardCMeans2.PNG|thumb|400px|center|Рисунок 2. Подробное описание работы блока  &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039;. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (по 1 значению центра кластера на каждую из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; соответствующих вершин графа и значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;, единое для этого &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039;-блока), &#039;&#039;&#039;&#039;&#039;d1,...,dC&#039;&#039;&#039;&#039;&#039; — прямое вычисление  расстояния до кластерных центров, &#039;&#039;&#039;&#039;&#039;min&#039;&#039;&#039;&#039;&#039; — вычисление минимума двух чисел (с сохранением соответствующего минимуму кластерного индекса) и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (индекс кластерного центра, расположенного ближе всего к точке &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;, и соответствующее расстояние).]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
Для выполнения одной итерации алгоритма C средних необходимо выполнить параллельно ряд вычислений для каждого из &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; элементов:&lt;br /&gt;
&lt;br /&gt;
# Вычисление &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; расстояний между элементом и кластерными центрами.&lt;br /&gt;
# Выполнение &amp;lt;math&amp;gt;(C - 1)&amp;lt;/math&amp;gt; сравнений для определения минимального.&lt;br /&gt;
# Определение значений соответствующего рассматриваемому элементу &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; столбца матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Эта последовательность операций может быть выполнена для каждого элемента &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; входной выборки независимо и поэтому составляет основной ресурс параллелизма алгоритма.&lt;br /&gt;
&lt;br /&gt;
При этом, как можно видеть из информационного графа алгоритма, часть вычислений проводится в последовательном режиме, например, расчёт значения объектной функции &amp;lt;math&amp;gt;J&amp;lt;/math&amp;gt;. Аналогичная ситуация имеет место и с пересчётом кластерных центров — разделив эту операцию на &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; независимых процессов, мы потеряем в производительности за счёт увеличения накладных расходов, связанных с пересылкой данных и координацией вычислений.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что при малом объёме выборки и размерности системы попытка использования параллельной реализации алгоритма приведёт к понижению производительности, поскольку проведение последовательных расчётов потребует меньше времени, нежели пересылка данных (хотя бы матриц размера &amp;lt;math&amp;gt;nC&amp;lt;/math&amp;gt;, определяющих кластерные центры).&lt;br /&gt;
&lt;br /&gt;
При этом, как легко видеть, ширина [[глоссарий#Ярусно-параллельная форма графа алгоритма|ЯПФ]] составляет &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt; (если быть точнее, просто &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;). Высота ЯПФ для строгого алгоритма C средних оценивается как &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt; (предполагаем, что число итераций существенно меньше объёма выборки &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; &lt;br /&gt;
*&amp;lt;math&amp;gt;\{u_k\}_{k=1}^{N} \subset \mathbb{R}^n&amp;lt;/math&amp;gt; — исходный набор векторов;&lt;br /&gt;
*&amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; — количество кластеров (&amp;lt;math&amp;gt;2 \leqslant C \leqslant N&amp;lt;/math&amp;gt;);&lt;br /&gt;
* &#039;&#039;(опционально)&#039;&#039; &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; — пороговая точность работы алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;nN+1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
*&amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; — рядовая матрица из пространства &amp;lt;math&amp;gt;\mathbb{R}^{C \times N}&amp;lt;/math&amp;gt;.&lt;br /&gt;
*&amp;lt;math&amp;gt;\{c_k\}_{k=1}^{C}&amp;lt;/math&amp;gt; — набор построенных кластерных центров.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;C(N+n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Назначение:&#039;&#039;&#039; кластеризация больших наборов числовых данных.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Достоинства:&#039;&#039;&#039;&lt;br /&gt;
* лёгкость реализации;&lt;br /&gt;
* вычислительная простота.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Недостатки:&#039;&#039;&#039;&lt;br /&gt;
* нет гарантии, что итерационный процесс сойдётся к оптимальному решению;&lt;br /&gt;
* производительность существенно зависит от выбора начальных кластерных центров.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
Исследуем масштабируемость параллельной реализации строгого алгоритма C средних, соответствующей последовательной реализации, описанной в [[#Схема реализации последовательного алгоритма|п1.5]]. Для проведения расчётов использовались ресурсы вычислительного комплекса IBM Blue Gene/P и собственная реализация алгоритма, поскольку в открытом доступе параллельные реализации алгоритма авторами найдены не были ([[#Существующие реализации алгоритма|п2.7]]).&lt;br /&gt;
&lt;br /&gt;
Набор и границы значений изменяемых параметров запуска реализации алгоритма:&lt;br /&gt;
&lt;br /&gt;
* число процессоров &amp;lt;math&amp;gt;[16 : 256]&amp;lt;/math&amp;gt; с шагом по степеням двойки;&lt;br /&gt;
* объём выборки &amp;lt;math&amp;gt;[10^3:10^7]&amp;lt;/math&amp;gt;  с шагом по степеням десятки;&lt;br /&gt;
* размерность системы &amp;lt;math&amp;gt;n=10&amp;lt;/math&amp;gt;;&lt;br /&gt;
* количество кластеров &amp;lt;math&amp;gt;C = 11&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве изменяемого параметра для построения графика был выбран объём выборки &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, поскольку варьирование прочих параметров существенно хуже отражает возможности применения технологии параллельных вычислений. Это связано с тем, что при малом количестве векторов время, затраченное на пересылку данных, сравнимо со временем, затрачиваемым непосредственно на расчёты; это хорошо видно на графике: при объёмах выборки, составляющих &amp;lt;math&amp;gt;10^3&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;10^4&amp;lt;/math&amp;gt; векторов, использование большего числа процессоров не приводит к приросту производительности (наоборот, производительность падает) ввиду высоких накладных расходов.&lt;br /&gt;
&lt;br /&gt;
[[file:HardCMeansPerfomance.png|thumb|center|700px|Рис.3 Реализация строгого алгоритма C средних. График производительности (GFLOPS) в зависимости от числа параллельных процессов и объёма выборки.]]&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
1)  [https://github.com/artpar/Hard-Clustering-implementation Последовательная реализация на С++ ]&lt;br /&gt;
&lt;br /&gt;
2) [http://projects.jasmeet.me/2013/03/HardCMeans.html Последовательная реализация на MatLab ]&lt;br /&gt;
&lt;br /&gt;
На момент публикации параллельных реализаций в свободном доступе обнаружено не было.&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Coctic</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE&amp;diff=17858</id>
		<title>Обсуждение участника:Светлана Лукьяненко</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE&amp;diff=17858"/>
		<updated>2016-11-17T07:38:02Z</updated>

		<summary type="html">&lt;p&gt;Coctic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Статья [[Участник:Светлана Лукьяненко/Строгий алгоритм С средних (Hard C-Means, HCM)]] =&lt;br /&gt;
* Не указан вклад каждого автора [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:57, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:05, 31 октября 2016 (MSK)&lt;br /&gt;
* Значительная часть п. 1.2  совпадает с тем же пунктом из [[Участник:Каледа Александр/Строгий алгоритм С средних (Hard C-Means)]] [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:05, 25 октября 2016 (MSK)&lt;br /&gt;
** Замечание снимается [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:05, 31 октября 2016 (MSK)&lt;br /&gt;
* В списке литературы отсутствуют выходные данные публикаций, кроме названия и автора. По приведенным данным определить конкретную публикацию не представляется возможным. Стоит добавить ссылку на оригинальную публикацию с описанием алгоритма, упомянутую в начале п.1.1 [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:57, 25 октября 2016 (MSK)&lt;br /&gt;
** Не исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:05, 31 октября 2016 (MSK)&lt;br /&gt;
* Список литературы совпадает со списком из [[Участник:Каледа Александр/Строгий алгоритм С средних (Hard C-Means)]] [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:01, 25 октября 2016 (MSK)&lt;br /&gt;
** Замечание снимается [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:05, 31 октября 2016 (MSK)&lt;br /&gt;
----------------------&lt;br /&gt;
* Комментарий от [[Участник:Юрий Комаров|Комарова Юрия]]: Сравните, пожалуйста, нашу историю работы над статьёй с историей работы над статьёй наших коллег: Каледы и его товарища. Сделав это, Вы обнаружите, что мы начали работать сразу же после выдачи задания, практически одними из первых и гораздо раньше указанных ребят, и неоднократно правили каждый из пунктов, доводя их до лучшей кондиции. За то, что пункт 1.2, как, впрочем, и другие пункты, и список литературы были составлены нами лично в процессе длительной совместной работы со [[Участник:Светлана Лукьяненко|Светланой]], отвечаю головой. Надеюсь, вопрос о плагиате больше не возникнет. В такой ситуации исправлять что-то должны явно не мы. С уважением, Комаров Юрий.&lt;br /&gt;
** В мои задачи не входить обвинять кого-то в плагиате, проводить расследования, кто у кого списал, или выяснять, кто прав, а кто нет. Меня попросили проверить статью, обращая внимание на пересечения с другими на ту же тему. В двух статьях есть общая часть, это пошло в замечания к обеим статьям. Пересечение уйдет - замечание снимется. Кто исправит текст - мне все равно. Когда в статье появится метка, что ее можно снова проверять - я сравню тексты снова. Пока текст совпадает - замечание с моей стороны остается. Есть А.С. Антонов, если он сочтет, что это замечание можно проигнорировать (в одной статье или в обеих) - он продвинет статью дальше. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 18:31, 28 октября 2016 (MSK)&lt;br /&gt;
** Если говорить о, скажем мягко, некорректном заимствовании, то ваш п 1.2 есть воспроизведение фрагмента из работы Нейского с небольшими добавлениями. У вас имеется разрешение автора на такое воспроизведение? Так что не стоит так сразу головой-то... [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 18:31, 28 октября 2016 (MSK)&lt;br /&gt;
** В общем, не стоит отвечать в таком тоне. Я могу понять возмущение, но писать надо корректнее. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 18:31, 28 октября 2016 (MSK)&lt;br /&gt;
* Вклад авторов указан, в источниках приведены ссылки. Исправлять часть статьи, которую у нас украли наши коллеги (дата создания их страницы 15 октября), должны не мы, а указанные личности. К сожалению, заставить их это сделать мы не можем, полагаю, регулирование этого вопроса нам разумнее доверить проверяющим.&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
* В списке литературы отсутствуют выходные данные публикаций, кроме названия и автора. По приведенным данным определить конкретную публикацию не представляется возможным. Стоит добавить ссылку на оригинальную публикацию с описанием алгоритма, упомянутую в начале п.1.1  [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:05, 31 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:06, 3 ноября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
* п. 2.4. Не приведена ссылка на текст анализируемой программы. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:38, 17 ноября 2016 (MSK)&lt;/div&gt;</summary>
		<author><name>Coctic</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:%D0%9A%D0%B0%D0%BB%D0%B5%D0%B4%D0%B0_%D0%90%D0%BB%D0%B5%D0%BA%D1%81%D0%B0%D0%BD%D0%B4%D1%80/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%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_(Hard_C-Means)&amp;diff=17857</id>
		<title>Участник:Каледа Александр/Строгий алгоритм С средних (Hard C-Means)</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:%D0%9A%D0%B0%D0%BB%D0%B5%D0%B4%D0%B0_%D0%90%D0%BB%D0%B5%D0%BA%D1%81%D0%B0%D0%BD%D0%B4%D1%80/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%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_(Hard_C-Means)&amp;diff=17857"/>
		<updated>2016-11-17T07:35:13Z</updated>

		<summary type="html">&lt;p&gt;Coctic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Строгий алгоритм С средних (Hard C-Means)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;nm+1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;(n+m)C&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы описания: [[Участник:Каледа_Александр|Каледа Александр]] (разделы [[#Общее описание алгоритма|1.1]], [[#Схема реализации последовательного алгоритма|1.5]], [[#Последовательная сложность алгоритма|1.6]], [[#Информационный граф|1.7]], [[#Ресурс параллелизма алгоритма|1.8]], [[#Входные и выходные данные алгоритма|1.9]]), [[Участник:Шапулин_Андрей|Шапулин Андрей]] (разделы [[#Математическое описание алгоритма|1.2]], [[#Вычислительное ядро алгоритма|1.3]], [[#Макроструктура алгоритма|1.4]], [[#Информационный граф|1.7]], [[#Свойства алгоритма|1.10]], [[#Существующие реализации алгоритма|2.7]]).&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Строгий алгоритм C средних&#039;&#039;&#039; (&#039;&#039;&#039;&#039;&#039;Hard C-Means, HCM&#039;&#039;&#039;&#039;&#039;; &#039;&#039;Jang, Sun and Mizutani, 1997&#039;&#039;) один из наиболее широко используемых алгоритмов кластеризации данных&amp;lt;ref&amp;gt;[http://faculty.petra.ac.id/resmana/private/fuzzy/nfmod.pdf Jantzen J. Neurofuzzy Modelling. 1998. Электронное издание. 28 Стр.]&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;
# Пересчёт кластерных центров.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
Исходные данные: матрица &amp;lt;math&amp;gt;U\in \mathbb{R}^{n\times m}&amp;lt;/math&amp;gt;, представляющая собой набор векторов &amp;lt;math&amp;gt;\{u_i\}_{i=1}^{n}, u_i \in \mathbb{R}^m&amp;lt;/math&amp;gt;; количество кластеров &amp;lt;math&amp;gt;C \in \mathbb{N}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные: набор векторов - кластерных центров &amp;lt;math&amp;gt;\{c_i\}_{i=1}^{C}, c_i \in \mathbb{R}^m&amp;lt;/math&amp;gt;; матрица &amp;lt;math&amp;gt;M\in \mathbb{N}^{n\times C}&amp;lt;/math&amp;gt; c информацией о разбиении объектов на кластера. Элемент &amp;lt;math&amp;gt;m_{ij}=1&amp;lt;/math&amp;gt;, если &amp;lt;math&amp;gt;u_j \in C_i&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; содержит все объекты &amp;lt;math&amp;gt;u&amp;lt;/math&amp;gt;, принадлежащие кластеру &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;. Остальные элементы &amp;lt;math&amp;gt;m_{ij}=0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм:&lt;br /&gt;
&lt;br /&gt;
Шаг 1. Инициализация кластерных центров &amp;lt;math&amp;gt;c_i, i = 1, 2, \dots, C.&amp;lt;/math&amp;gt; Это можно сделать выбрав случайным образом C векторов из входного набора &amp;lt;math&amp;gt;\{u_i\}_{i=1}^{n}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Шаг 2. Вычисление рядовой матрицы M. &lt;br /&gt;
&lt;br /&gt;
Матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; состоит из элементов &amp;lt;math&amp;gt;M = \|m_{ik}\|&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ik} = \begin{cases}&lt;br /&gt;
1, &amp;amp; \|u_k-c_i\|^2 \leqslant \|u_k-c_j\|^2 \;\; \text{for all } i \neq j; \;\; (i,j=1,2,\ldots,C; \; k = 1,2,\ldots,n)\\&lt;br /&gt;
0, &amp;amp; \text{otherwise}.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Шаг 3. Расчет объектной функции: &lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^C J_i = \sum\limits_{i=1}^C \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
На этом шаге происходит остановка и выход из цикла, если полученное значение ниже пороговой величины или полученное значение не сильно отличается от значений, полученных на предыдущих циклах.&lt;br /&gt;
&lt;br /&gt;
Шаг 4. Пересчет кластерных центров. &lt;br /&gt;
&lt;br /&gt;
Пересчет кластерных центров выполняется в соответствии со следующим уравнением: &lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где &amp;lt;math&amp;gt;|C_i|&amp;lt;/math&amp;gt; -- количество элементов в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом кластере.&lt;br /&gt;
&lt;br /&gt;
Шаг 5. Переход на шаг 2.&lt;br /&gt;
&lt;br /&gt;
Описание взято из &amp;lt;ref&amp;gt;[http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf Нейский И.М. Классификация и сравнение методов кластеризации // Интеллектуальные технологии и системы. Сборник учебно-методических работ и статей аспирантов и студентов. – М.: НОК «CLAIM», 2006. – Выпуск 8. – С. 130-142.]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма Hard C-Means можно составить из множественных (всего их &amp;lt;math&amp;gt;nC&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;: &amp;lt;math&amp;gt;\|u_k-c_i\|^2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Как записано и в описании ядра алгоритма, основную часть метода составляют множественные (&amp;lt;math&amp;gt;Cn&amp;lt;/math&amp;gt;) вычисления квадратов норм:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\|u_k-c_i\|^2&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;&lt;br /&gt;
J = \sum\limits_{i=1}^C J_i = \sum\limits_{i=1}^C \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right)&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Поэлементное суммирование векторов:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Итерационный блок алгоритма можно описать на языке Python следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python3&amp;quot;&amp;gt;&lt;br /&gt;
for i in range(n):&lt;br /&gt;
    idx_min = 0&lt;br /&gt;
    dist_min  = ((u[i] - c[0]) ** 2).sum()&lt;br /&gt;
&lt;br /&gt;
    for j in range(1, C):&lt;br /&gt;
        dist  = ((u[i] - c[j]) ** 2).sum()&lt;br /&gt;
        if dist &amp;lt; dist_min:&lt;br /&gt;
            idx_min = j&lt;br /&gt;
            dist_min = dist&lt;br /&gt;
&lt;br /&gt;
    M[i, idx_min] = 1&lt;br /&gt;
    c_next[idx_min] += u[i]&lt;br /&gt;
    c_next_cnt[idx_min] += 1&lt;br /&gt;
    J += dist_min&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
Предполагаем, что предельная точность алгоритма достигаема менее, чем за &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; итераций. Иначе использование алгоритма можно считать нерациональным. Также предположим, что размерность &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; и количество кластерных центров &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; существенно меньше &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Операция вычисления квадрата нормы разности векторов требует выполнения &amp;lt;math&amp;gt;m-1&amp;lt;/math&amp;gt; арифметических операций сложения, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; операций вычитания и &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
&lt;br /&gt;
Каждая итерация алгоритма требует выполнения:&lt;br /&gt;
* &amp;lt;math&amp;gt;nC&amp;lt;/math&amp;gt; операций вычисления квадрата нормы разности векторов;&lt;br /&gt;
* &amp;lt;math&amp;gt;nC&amp;lt;/math&amp;gt; операций сравнения квадрата нормы;&lt;br /&gt;
* &amp;lt;math&amp;gt;3n&amp;lt;/math&amp;gt; операций сложения;&lt;br /&gt;
&lt;br /&gt;
Таким образом, на каждой итерации имеем:&lt;br /&gt;
* &amp;lt;math&amp;gt;mnC&amp;lt;/math&amp;gt; операций умножения;&lt;br /&gt;
* &amp;lt;math&amp;gt;(2mC + 3)n&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания;&lt;br /&gt;
&lt;br /&gt;
В итоге имеем сложность последовательной реализации алгоритма &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Граф алгоритма состоит из 4 видов вершин:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первая&#039;&#039;&#039; группа вершин отмечена символом &#039;&#039;&#039;&#039;&#039;M&#039;&#039;&#039;&#039;&#039;. Ей соответствует вычисление минимального расстояния до кластерных центров, а также запись единицы в соответствующий столбец матрицы, обозначающей принадлежность кластерному центру:&lt;br /&gt;
* независимое вычисление расстояний от заданного элемента &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; до каждого из кластерных центров;&lt;br /&gt;
* последовательное сравнение полученных значений с целью отыскания максимума;&lt;br /&gt;
* операция записи 1 в соответствующий столбец матрицы принадлежности кластерным центрам;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вторая&#039;&#039;&#039; вершина отмечена символом &#039;&#039;&#039;&#039;&#039;J&#039;&#039;&#039;&#039;&#039;, на этом этапе происходит итоговый расчёт объектной функции.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Третья&#039;&#039;&#039; вершина помечена &#039;&#039;&#039;&#039;&#039;if&#039;&#039;&#039;&#039;&#039;, на этом этапе происходит проверка условия достижения требуемой точности.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Четвертая&#039;&#039;&#039; соответствует операции пересчёта кластерных центров, она отмечена как &#039;&#039;&#039;&#039;&#039;C&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
[[File:Cmeans.png|thumb|800px|center|Рисунок 1. Информационный граф алгоритма. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных, &#039;&#039;&#039;&#039;&#039;D&#039;&#039;&#039;&#039;&#039; — вычисление минимального расстояния до кластерных центров и проставление принадлежности соответствующему кластерному центру, &#039;&#039;&#039;&#039;&#039;J&#039;&#039;&#039;&#039;&#039; — вычисление объектной функции по результатам полученных вычислений, &#039;&#039;&#039;&#039;&#039;if&#039;&#039;&#039;&#039;&#039; — проверка условия достижения желаемой точности, &#039;&#039;&#039;&#039;&#039;C&#039;&#039;&#039;&#039;&#039; — пересчёт кластерных центров и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
Основной ресурс параллелизма алгоритма составляет итерационный блок. Эта последовательность итераций может быть выполнена для каждого входного вектора &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; независимо. Однако, в конце выполнения каждого итерационного блока имеют место последовательные вычисления - сложение значений объектной функции, полученных независимо на каждом процессоре, а также перерасчет кластерных центров.&lt;br /&gt;
&lt;br /&gt;
Высота [[глоссарий#Ярусно-параллельная форма графа алгоритма|ЯПФ]] оценивается как &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt; (при условии, что число итераций существенно меньше объёма выборки &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;). Ширина [[глоссарий#Ярусно-параллельная форма графа алгоритма|ЯПФ]] равна &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Необходимо учитывать, что при небольшом объеме входной выборки, параллельная реализация алгоритма может лишь понизить производительность. В первую очередь это связано с пересылкой данных для вычисления итоговых значений объектной функции и кластерных центров.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; матрица &amp;lt;math&amp;gt;U\in \mathbb{R}^{n\times m}&amp;lt;/math&amp;gt;, представляющая собой набор векторов &amp;lt;math&amp;gt;\{u_i\}_{i=1}^{n}, u_i \in \mathbb{R}^m&amp;lt;/math&amp;gt;; количество кластеров &amp;lt;math&amp;gt;C \in \mathbb{N}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;nm+1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; набор векторов - кластерных центров &amp;lt;math&amp;gt;\{c_i\}_{i=1}^{C}, c_i \in \mathbb{R}^m&amp;lt;/math&amp;gt;; матрица &amp;lt;math&amp;gt;M\in \mathbb{N}^{n\times C}&amp;lt;/math&amp;gt; c информацией о разбиении объектов на кластера. Элемент &amp;lt;math&amp;gt;m_{ij}=1&amp;lt;/math&amp;gt;, если &amp;lt;math&amp;gt;u_j \in C_i&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; содержит все объекты &amp;lt;math&amp;gt;u&amp;lt;/math&amp;gt;, принадлежащие кластеру &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;. Остальные элементы &amp;lt;math&amp;gt;m_{ij}=0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;(n+m)C&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
Достоинства:&lt;br /&gt;
&lt;br /&gt;
* лёгкость реализации;&lt;br /&gt;
* вычислительная простота;&lt;br /&gt;
* может служить для кластеризации больших наборов числовых данных;&lt;br /&gt;
&lt;br /&gt;
Недостатки:&lt;br /&gt;
&lt;br /&gt;
* задание количества кластеров;&lt;br /&gt;
* отсутствие гарантии в нахождении оптимального решения;&lt;br /&gt;
&lt;br /&gt;
Соотношение последовательной и параллельной сложности алгоритма: линейное.&lt;br /&gt;
&lt;br /&gt;
Вычислительная мощность алгоритма, как отношение числа операций к суммарному объему входных и выходных данных равна константе.&lt;br /&gt;
&lt;br /&gt;
Алгоритм является недетерминированным, т.к. он является итерационным с выходом по точности, а также использует датчик случайных чисел для инициализации кластерных центров.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===	&lt;br /&gt;
=== Локальность данных и вычислений ===	&lt;br /&gt;
==== Локальность реализации алгоритма ====	&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====	&lt;br /&gt;
===== Количественная оценка локальности =====	&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
Проведём исследование масштабируемости параллельной реализации строгого алгоритма C средних согласно [[Scalability methodology|методике]]. &lt;br /&gt;
&lt;br /&gt;
Набор и границы значений изменяемых [[Глоссарий#Параметры запуска|параметров запуска]] реализации алгоритма: &lt;br /&gt;
&lt;br /&gt;
*	число процессоров [1 : 48] с шагом 1;&lt;br /&gt;
*	размерность пространства [3 : 50] c шагом 3;&lt;br /&gt;
*	число векторов 100 000 000;&lt;br /&gt;
*	число кластерных центров 30;&lt;br /&gt;
&lt;br /&gt;
В результате проведённых экспериментов был получен следующий диапазон [[Глоссарий#Эффективность реализации|эффективности реализации]] алгоритма:&lt;br /&gt;
&lt;br /&gt;
*	минимальная эффективность реализации 0.014;&lt;br /&gt;
*	максимальная эффективность реализации 0.9.&lt;br /&gt;
&lt;br /&gt;
На следующих рисунках приведены графики [[Глоссарий#Производительность|производительности]] и эффективности выбранной реализации HCM в зависимости от изменяемых параметров запуска.&lt;br /&gt;
&lt;br /&gt;
[[file:GFLOPS_AA.png|thumb|center|700px|Рисунок 2. Параллельная реализация алгоритма. Изменение производительности в зависимости от числа процессоров и размерности векторов.]]&lt;br /&gt;
[[file:EFFICIENCY.png|thumb|center|700px|Рисунок 3. Параллельная реализация алгоритма. Изменение эффективности в зависимости от числа процессоров и размерности векторов.]]&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
* [http://projects.jasmeet.me/2013/03/HardCMeans.html Последовательная реализация алгоритма на MatLab]&lt;br /&gt;
* [https://github.com/artpar/Hard-Clustering-implementation Последовательная реализация алгоритма на С++]&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Coctic</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:%D0%9A%D0%B0%D0%BB%D0%B5%D0%B4%D0%B0_%D0%90%D0%BB%D0%B5%D0%BA%D1%81%D0%B0%D0%BD%D0%B4%D1%80&amp;diff=17856</id>
		<title>Обсуждение участника:Каледа Александр</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:%D0%9A%D0%B0%D0%BB%D0%B5%D0%B4%D0%B0_%D0%90%D0%BB%D0%B5%D0%BA%D1%81%D0%B0%D0%BD%D0%B4%D1%80&amp;diff=17856"/>
		<updated>2016-11-17T07:35:02Z</updated>

		<summary type="html">&lt;p&gt;Coctic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Статья [[Участник:Каледа Александр/Строгий алгоритм С средних (Hard C-Means)]] =&lt;br /&gt;
* Не указан вклад каждого автора [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:08, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:42, 2 ноября 2016 (MSK)&lt;br /&gt;
* Стоит добавить ссылку на оригинальную публикацию, в которой был впервые предложен алгоритм. [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:08, 25 октября 2016 (MSK)&lt;br /&gt;
** Не исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:42, 2 ноября 2016 (MSK)&lt;br /&gt;
* Значительная часть п. 1.2  совпадает с тем же пунктом из [[Строгий алгоритм С средних (Hard C-Means, HCM)]]&lt;br /&gt;
** Замечание снимается [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:42, 2 ноября 2016 (MSK)&lt;br /&gt;
* Пункты раздела 2 не соответствуют шаблону. П. 2.1 должен быть 2.4, п. 2.2 должен быть 2.7, остальные пункты пропущены [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:08, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:42, 2 ноября 2016 (MSK)&lt;br /&gt;
* В списке литературы отсутствуют выходные данные публикаций, кроме названия и автора. По приведенным данным определить конкретную публикацию не представляется возможным. [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:08, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:42, 2 ноября 2016 (MSK)&lt;br /&gt;
* Список литературы совпадает со списком из [[Строгий алгоритм С средних (Hard C-Means, HCM)]] [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:08, 25 октября 2016 (MSK)&lt;br /&gt;
** Замечание снимается [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:42, 2 ноября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
------------&lt;br /&gt;
* Стоит добавить ссылку на оригинальную публикацию, в которой был впервые предложен алгоритм [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:42, 2 ноября 2016 (MSK)&lt;br /&gt;
* п. 2.4.1 пустой. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:35, 17 ноября 2016 (MSK)&lt;br /&gt;
* п. 2.4.2. Отсутствует ссылка на текст исследуемой программы и аппаратную платформу, на которой проводилось тестирование. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:35, 17 ноября 2016 (MSK)&lt;br /&gt;
* Рис. 3. В подписи к рисунку не указано, график зависимости эффективности какого типа приведен. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:35, 17 ноября 2016 (MSK)&lt;/div&gt;</summary>
		<author><name>Coctic</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=17855</id>
		<title>Участник:Gkhazeeva/Нечеткий алгоритм C средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Gkhazeeva/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_C_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=17855"/>
		<updated>2016-11-17T07:29:18Z</updated>

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

		<summary type="html">&lt;p&gt;Coctic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Статья [[Нечеткий алгоритм C средних]] =&lt;br /&gt;
* Не указан вклад каждого автора [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:54, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:55, 1 ноября 2016 (MSK)&lt;br /&gt;
* п. 1.2 номера формул следует выравнивать по правому краю, а не прилеплять вплотную к формуле [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:54, 25 октября 2016 (MSK)&lt;br /&gt;
** Условно исправлено. Форматирование сделано негодными средствами, но неясно, установлены ли средства (https://en.wikipedia.org/wiki/Help:Displaying_a_formula#Equation_numbering), чтобы сделать правильно [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:55, 1 ноября 2016 (MSK)&lt;br /&gt;
*** Пробовал сделать указанными Вами средствами - на этом ресурсе указанные Вами шаблоны не заработали [[Участник:Yushin|Павел Юшин]]&lt;br /&gt;
* п. 1.3 состоит из одного предложения и не дает достаточно информации [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:54, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:55, 1 ноября 2016 (MSK)&lt;br /&gt;
* п. 1.7 приведенный рисунок не является информационным графом: не все дуги ориентированы, имеются циклы [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:54, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:55, 1 ноября 2016 (MSK)&lt;br /&gt;
* п. 1.9 не приведено оценки объема входных и выходных данных [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:54, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:55, 1 ноября 2016 (MSK)&lt;br /&gt;
* в разделе 2 отсутствуют необходимые пункты, п. 2.2 должен быть 2.7 [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:54, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:55, 1 ноября 2016 (MSK)&lt;br /&gt;
* В списке литературы 1 ссылка - скопированный шаблон без реальной ссылки, 2 ссылка - просто URL без выходных данных источника [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:54, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено частично. Ссылка 2 по-прежнему не имеет достаточных выходных данных [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:55, 1 ноября 2016 (MSK)&lt;br /&gt;
*** На сайте, где студентам выдавалось задание ( http://parallel.ru/ss16 ), данный материал предоставлялся в списке источников (номер [8]) в таком же виде, как он указан в данной статье [[Участник:Yushin|Павел Юшин]]&lt;br /&gt;
**** Не вижу никакого противоречия с тем, что я написал в замечании [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:47, 7 ноября 2016 (MSK)&lt;br /&gt;
**** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 16:34, 13 ноября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
* п. 2.4. Приведен график зависимости эффективности от параметров задачи. Не указано, о какой конкретно эффективности идет речь. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:29, 17 ноября 2016 (MSK)&lt;/div&gt;</summary>
		<author><name>Coctic</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:Nikmedoed/%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_(Fuzzy_C-means)&amp;diff=17853</id>
		<title>Участник:Nikmedoed/Нечеткий алгоритм С-средних (Fuzzy C-means)</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:Nikmedoed/%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_(Fuzzy_C-means)&amp;diff=17853"/>
		<updated>2016-11-17T07:27:24Z</updated>

		<summary type="html">&lt;p&gt;Coctic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм С-средних (Fuzzy C-means)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(c^2 MI + cMnI), (I&amp;lt;/math&amp;gt; - число итераций, &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - число точек, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - размерность точек (свойств на объект)&amp;lt;math&amp;gt;)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;Mn&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;cM&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt; O(c^2 I + cnI)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O( M )&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы: [[Участник:Nikmedoed|Н.А. Муромцев]] - перенос в вики, раздел 2, картинки, [[Участник:illusive_mike|М.С. Дворецкий]] - раздел 1&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Нечеткий алгоритм С-средних&#039;&#039;&#039; (&#039;&#039;Fuzzy C-means&#039;&#039;) - позволяет получить нечёткую кластеризацию больших наборов числовых данных, что позволяет корректно определять объекты на границах кластеров. Однако, выполнение данного алгоритма требует серьёзных вычислительных ресурсов, а также изначального задания количества кластеров. Кроме того, может возникнуть неоднозначность с объектами, удалёнными от центров всех кластеров.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Алгоритм кластеризации Fuzzy C-Means (FCM) был предложен Дж. Данном в 1973 году &amp;lt;ref&amp;gt;Dunn, J.C.: A Fuzzy Relative of the ISODATA Process and Its Use in Detecting Compact Well-Separated Clusters. Journal of Cybernetics. 3 (1973): 32–57&amp;lt;/ref&amp;gt; и доработан Дж. Бездеком в 1981 году &amp;lt;ref&amp;gt;Bezdek, J.C.: Pattern Recognition with Fuzzy Objective Function Algorithms. Plenum Press, New York (1981). ISBN 0-306-40671-3&amp;lt;/ref&amp;gt;. В отличие от большинства существующих алгоритмов кластеризации, данный алгоритм является нечётким – каждый из объектов не входит однозначно в какой-либо кластер, а принадлежит всем кластерам с различными степенями принадлежности. Это даёт преимущества в качестве разбиения в случаях, когда кластеры находятся близко друг к другу, и большое число точек находится на их границах. Однако ценой такой нечёткости служат большие вычислительные затраты, чем у таких чётких алгоритмов, как [[Hard C-Means]] и [[K-Means]], при сохранении таких их недостатков, как априорное определение числа кластеров и отсутствие гарантии глобальной оптимальности результата.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Исходные данные: массив объектов &amp;lt;math&amp;gt;{X_k}\in{\R^n}, k=\overline{1,M}&amp;lt;/math&amp;gt;, число кластеров c, экспоненциальный вес &amp;lt;math&amp;gt;m\in{[1,\infty)}&amp;lt;/math&amp;gt;, параметр останова &amp;lt;math&amp;gt;\varepsilon&amp;gt;0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные: матрица разбиения &amp;lt;math&amp;gt;F&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;M\times c&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;\mu_{ki}\in[0,1]&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\sum^{c}_{i=1} {\mu_{ki}} = 1&amp;lt;/math&amp;gt;), центры кластеров &amp;lt;math&amp;gt;V_i&amp;lt;/math&amp;gt;, расстояния &amp;lt;math&amp;gt;D_{ki}&amp;lt;/math&amp;gt; между объектами и центрами кластеров.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Формулы метода (вычисляются последовательно на каждой итерации):&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
1. Уточнение центров кластеров по степеням принадлежности&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
&amp;amp;V_i=\frac{\sum^{M}_{k=1} {\mu^m_{ki} * X_k}}{\sum^{M}_{k=1} {\mu^m_{ki}}},i=\overline{1,c}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
2. Расчёт расстояний между новыми центрами кластеров и точками данных&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
&amp;amp;D_{ki}=\sqrt{{\lVert X_k - V_i \rVert}^2},k=\overline{1,M},i=\overline{1,c}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
3. Пересчёт степеней принадлежности объектов кластерам&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
&amp;amp;\mu_{ki}=\frac{1}{{ \sum^{c}_{j=1} \left ( {\frac{D_{ki}}{D_{kj}}} \right ) }^{{2}/{m-1}}&lt;br /&gt;
},k=\overline{1,M},i=\overline{1,c}\\&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На каждой итерации алгоритма происходит уточнение элементов матрицы &amp;lt;math&amp;gt;F&amp;lt;/math&amp;gt;. Выходом алгоритма служит матрица &amp;lt;math&amp;gt;F&amp;lt;/math&amp;gt;, к которой алгоритм сходится. Факт того, что алгоритм сошёлся, устанавливается проверкой вида &amp;lt;math&amp;gt;\max_{k = \overline{1,M},i = \overline{1,c}} {( \left | \mu_{ki} - \mu_{ki}^* \right |)} &amp;lt; \varepsilon&amp;lt;/math&amp;gt;  либо  &amp;lt;math&amp;gt;\max_{i = \overline{1,c}} {( \left | V_i - V_i^* \right |)} &amp;lt; \varepsilon&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\mu_{ki}^* (V_i^*)&amp;lt;/math&amp;gt; – значение &amp;lt;math&amp;gt;\mu_{ki}(V_i)&amp;lt;/math&amp;gt;, вычисленное на предыдущей итерации.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро алгоритма Fuzzy C-Means составляют шаги вычисления центров кластеров, расстояний между ними и точками данных и в особенности пересчёта матрицы степеней принадлежности точек данных.&lt;br /&gt;
&lt;br /&gt;
При реальном вычислении некоторые повторяющиеся вычисления могут быть устранены. Так, для шага вычисления центров кластеров величины &amp;lt;math&amp;gt;\mu_{ki}^m&amp;lt;/math&amp;gt; могут вычисляться однократно и умножаться на &amp;lt;math&amp;gt;X_k&amp;lt;/math&amp;gt; при включении в сумму, записанную в числителе. Для шага вычисления расстояний между центрами кластеров и точками, операция взятия квадратного корня не является обязательной, так как в дальнейшем на шаге вычисления степеней принадлежности можно непосредственно использовать квадраты этих расстояний, и сумма в знаменателе будет приобретать вид:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\sum^{c}_{j=1} {\left ( \frac{D_{ki} ^ {2}}{D_{kj} ^ {2}} \right )}^{{1}/{m-1}}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Алгоритм включает в себя три основных этапа – вычисление центров кластеров, вычисление расстояний между центрами кластеров и точками данных (включающее в себя макрооперации вычитания векторов и вычисления их норм, как правило в Евклидовом пространстве) и пересчёт матрицы принадлежности.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Последовательность исполнения алгоритма следующая:&lt;br /&gt;
&lt;br /&gt;
Инициализация происходит случайным заполнением матрицы принадлежности &amp;lt;math&amp;gt;F&amp;lt;/math&amp;gt; с соблюдением условия нормировки &amp;lt;math&amp;gt;\sum_{i=1}^c {\mu_{ki} =1}&amp;lt;/math&amp;gt; и переходом к шагу 1, либо случайным определением центров кластеров &amp;lt;math&amp;gt;V_i&amp;lt;/math&amp;gt; и переходом к шагу 2.&lt;br /&gt;
&lt;br /&gt;
Далее осуществляются итерации следующего вида:&lt;br /&gt;
&lt;br /&gt;
# &amp;lt;math&amp;gt;V_i=\frac{\sum_{k=1}^{M} {\mu_{ki}^m * X_k}}{\sum_{k=1}^{M} {\mu_{ki}^m} },i=\overline{1,c}&amp;lt;/math&amp;gt;&lt;br /&gt;
# &amp;lt;math&amp;gt;D_{ki}=\sqrt{{\lVert X_k - V_i \rVert}^2},k=\overline{1,M},i=\overline{1,c}&amp;lt;/math&amp;gt;&lt;br /&gt;
# &amp;lt;math&amp;gt;\mu_{ki}=\frac{1}{{ \sum^{c}_{j=1} {\left ( \frac{D_{ki}}{D_{kj}} \right )} }^{{2}/{m-1}}&lt;br /&gt;
},k=\overline{1,M},i=\overline{1,c}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В конце каждой итерации проверяется условие останова вида &amp;lt;math&amp;gt;\max_{k = \overline{1,M},i = \overline{1,c}} {( \left | \mu_{ki} - \mu_{ki}^* \right |)} &amp;lt; \varepsilon&amp;lt;/math&amp;gt;, либо &amp;lt;math&amp;gt;\max_{i = \overline{1,c}} {( \left | V_i - V_i^* \right |)} &amp;lt; \varepsilon&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\mu_{ki}^* (V_i^*)&amp;lt;/math&amp;gt; – значение &amp;lt;math&amp;gt;\mu_{ki}(V_i)&amp;lt;/math&amp;gt;, вычисленное на предыдущей итерации. Если условие не выполнено, осуществляется переход к шагу 1.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
При кластеризации &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; объектов данных, представленных точками в &amp;lt;math&amp;gt;\R^n&amp;lt;/math&amp;gt;, на &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; кластеров, алгоритм Fuzzy C-Means в последовательном варианте имеет вычислительную сложность – &amp;lt;math&amp;gt;O(c^2 MI+cMnI)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;I&amp;lt;/math&amp;gt; – число итераций. Если считать размерность данных &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; малой, то эта сложность сводится к &amp;lt;math&amp;gt;O(c^2 MI)&amp;lt;/math&amp;gt;. Основной частью алгоритма в этом случае является пересчёт матрицы принадлежностей, требующий вычисления &amp;lt;math&amp;gt;cM&amp;lt;/math&amp;gt; сумм из &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; слагаемых на каждой итерации.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
Приведём граф единичной итерации алгоритма в параллельном оптимизированном варианте (метод распараллеливания взят в &amp;lt;ref&amp;gt;Kwok, T., Smith, K.,&lt;br /&gt;
Lozano, S., Taniar, D.: [http://num-meth.srcc.msu.ru/zhurnal/tom_2012/pdf/v13r207.pdf Parallel Fuzzy c-Means Clustering for Large Data Sets], последнее обращение 25.10.2016&amp;lt;/ref&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
[[File:C-means_paralle_graph.png|thumb|upright=2.5|frame|center|alt=Paralel Fuzzy C-Means|Каждая вершина данного графа соответствует операциям из алгоритма, указанным при помощи указанных формул. Каждый из p столбцов соответствует работе одного из процессов. Пометки справа указывают число повторений каждого узла в ходе одной итерации.]]&lt;br /&gt;
&lt;br /&gt;
Раздел 1.8 уточняет, соответствуют ли эти повторения однотипным ярусам или точкам данных, вычисления для которых можно распараллелить и далее.&lt;br /&gt;
&lt;br /&gt;
Каждый процесс обладает следующими данными:&lt;br /&gt;
* координатами точек данных &amp;lt;math&amp;gt;X_k&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;k=\overline{1+rnk* \frac{M}{p},rnk*(\frac{M}{p}+1)}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;rnk&amp;lt;/math&amp;gt; – номер процесса,&lt;br /&gt;
* значениями &amp;lt;math&amp;gt;\mu_{ki}&amp;lt;/math&amp;gt; степени принадлежности для своих точек (&amp;lt;math&amp;gt;k=\overline{1+rnk* \frac{M}{p},rnk*(\frac{M}{p} +1)}, i=\overline{1,c}&amp;lt;/math&amp;gt;),&lt;br /&gt;
* координатами центров кластеров &amp;lt;math&amp;gt;V_i&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;i=\overline{1,c}&amp;lt;/math&amp;gt;.&lt;br /&gt;
Суммы &amp;lt;math&amp;gt;\sum_{k=1+rnk*\frac{M}{p}}^{rnk * ( \frac{M}{p} +1 )} {\mu_{ki}^m}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\sum_{k=1+rnk*\frac{M}{p}}^{rnk * ( \frac{M}{p} +1 )} {\mu_{ki}^m X_k}&amp;lt;/math&amp;gt; вычисляются одновременно, поэтому значения &amp;lt;math&amp;gt;\mu_{ki}^m&amp;lt;/math&amp;gt; вычисляются по одному разу за итерацию. Таким образом, второй ярус операций на рисунке на деле не содержит операций возведения в степень.&lt;br /&gt;
За счёт линейности большинства выражений относительно данных по точкам, процессы взаимодействуют только при редукции сумм, составляющих &amp;lt;math&amp;gt;V_i&amp;lt;/math&amp;gt;. Всё остальное время каждый процессор работает только со своими &amp;lt;math&amp;gt;\frac{M}{p}&amp;lt;/math&amp;gt; точками. Это обеспечивает применимость алгоритма для больших &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
При распараллеливании по точкам исходных данных и условии останову по малому изменению степеней принадлежности выполнение одной итерации алгоритма FCM может быть разделено на следующие ярусы:&lt;br /&gt;
* &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; ярусов нахождения частичных сумм знаменателя (по &amp;lt;math&amp;gt;\frac{M}{p}-1&amp;lt;/math&amp;gt; сложений, &amp;lt;math&amp;gt;\frac{M}{p}&amp;lt;/math&amp;gt; операций возведения в степень на процесс),&lt;br /&gt;
* &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; ярусов нахождения частичных сумм числителя (по &amp;lt;math&amp;gt;\frac{M}{p} -1&amp;lt;/math&amp;gt; сложений, &amp;lt;math&amp;gt;\frac{M}{p}&amp;lt;/math&amp;gt; умножений на процесс),&lt;br /&gt;
* &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; редукции сумм и передач значений &amp;lt;math&amp;gt;V_i&amp;lt;/math&amp;gt; процессам (получение &amp;lt;math&amp;gt;c(n+1)&amp;lt;/math&amp;gt; значений, &amp;lt;math&amp;gt;cn&amp;lt;/math&amp;gt; делений),&lt;br /&gt;
* &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; ярусов вычисления расстояний до центров (по &amp;lt;math&amp;gt;n-1&amp;lt;/math&amp;gt; сложений, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; вычитаний, &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений), каждый процесс получает &amp;lt;math&amp;gt;\frac{M}{p}&amp;lt;/math&amp;gt; точек на обработку,&lt;br /&gt;
* &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; ярусов вычисления степеней принадлежности точек (по &amp;lt;math&amp;gt;c+1&amp;lt;/math&amp;gt; делений, c возведений в степень, &amp;lt;math&amp;gt;c-1&amp;lt;/math&amp;gt; сложений), каждый процесс получает &amp;lt;math&amp;gt;\frac{M}{p}&amp;lt;/math&amp;gt; точек на обработку,&lt;br /&gt;
* до &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; ярусов проверки условий останова (по &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; вычитанию, &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; сравнению), каждый процесс получает &amp;lt;math&amp;gt;\frac{M}{p}&amp;lt;/math&amp;gt; точек на обработку,&lt;br /&gt;
* &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; редукция для обмена статусом завершения.&lt;br /&gt;
Таким образом, при распараллеливании по точкам исходных данных при условии наличия в каждом узле достаточного объёма памяти для хранения всего массива координат центров кластеров высота и ширина ЯПФ алгоритма FCM равны соответственно &amp;lt;math&amp;gt;O(c^2 I+cnI)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;O(M)&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;X_i&amp;lt;/math&amp;gt;, число кластеров &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;, экспоненциальный вес &amp;lt;math&amp;gt;m\in{[1,\infty)}&amp;lt;/math&amp;gt;, параметр останова &amp;lt;math&amp;gt;\varepsilon&amp;gt;0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;Mn&amp;lt;/math&amp;gt; для входных векторов, 3 вспомогательных параметра.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица принадлежности &amp;lt;math&amp;gt;F&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;\mu_{ki}\in[0,1]&amp;lt;/math&amp;gt;). Условие нормировки: &amp;lt;math&amp;gt;\sum^{c}_{i=1} {\mu_{ki}} = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;cM&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
В случае неограниченного распараллеливания по точкам данных (1 процесс на точку), отношение последовательной сложности алгоритма к параллельной пропорционально &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Параметр &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; задаёт степень «размытости» кластеров. В отсутствие априорных данных его обычно берут равным 2. В предельном случае сведения параметра &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; к значению 1, кластеры становятся чёткими и алгоритм вырождается в алгоритм кластеризации K-Means.&lt;br /&gt;
&lt;br /&gt;
Алгоритм недетерминирован, начальное положение кластеров задаётся случайно либо явно, либо опосредованно (через матрицу принадлежности). Алгоритм сходится к локальному экстремуму &amp;lt;ref&amp;gt;Höppner, F., Klawonn, F.: [https://public.fh wolfenbuettel.de/~klawonn/Papers/hoeppnerklawonntfs03.pdf A Contribution to Convergence Theory of Fuzzy c-Means and Derivatives], Дата последнего обращения: 13.10.2016&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;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
[[File:График.png|thumb|upright=2.5|frame|right|alt=Paralel Fuzzy C-Means time to iteration|График зависимости времени выполнения итерации параллельного нечеткого алгоритма С-средних (Fuzzy C-means) от количества процессоров и количества кластеризуемых вершин]]&lt;br /&gt;
&lt;br /&gt;
[[File:Effect_parallel_fuzzy_c-means.png|thumb|upright=2.5|frame|right|alt=Paralel Fuzzy C-Means efficiency|График эффективности параллельного нечеткого алгоритма С-средних (Fuzzy C-means) в зависимости от количества процессоров и количества кластеризуемых вершин.]]&lt;br /&gt;
&lt;br /&gt;
Исследование проведено на суперкомпьютере IBM Blue Gene/P&amp;lt;ref&amp;gt;[http://hpc.cs.msu.ru/bgp Описание вычислительного комплекса IBM Blue Gene/P]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
Для исследования была использована последовательная реализация алгоритма и реализован её [https://github.com/nikmedoed/Parallel-Fuzzy-C-means параллельный вариант]&amp;lt;ref&amp;gt;[https://github.com/nikmedoed/Parallel-Fuzzy-C-means Параллельная реализация алгоритма Fuzzy C-Means]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Для упрощения экспериментов было решено использовать количество вершин для кластеризации и количество процессов равное степени двойки, поэтому для каждого эксперимента были выбраны значения:&lt;br /&gt;
* &amp;lt;math&amp;gt;2^v, v=\overline{0,9}&amp;lt;/math&amp;gt;, для количества процессоров;&lt;br /&gt;
* &amp;lt;math&amp;gt;2^w, w=\overline{10,20}&amp;lt;/math&amp;gt;, для количества кластеризуемых вершин.&lt;br /&gt;
&lt;br /&gt;
Для одного набора значений проводилось 4 эксперимента и результаты усреднялись. При повторных запусках экспериментов значения выходили те же самые.&lt;br /&gt;
&lt;br /&gt;
Полученные результаты говорят о хорошей масштабируемости реализации алгоритма. Для большинства экспериментов эффективность находится в пределах 100±3%. Спад эффективности при малом числе вершин и большом числе процессоров обуславливается тем, что с уменьшением числа вершин, обрабатываемых каждым процессором, растёт доля времени обмена данных между процессорами, не зависящего от числа вершин.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
* пакет MATLAB &amp;lt;ref&amp;gt;[http://www.mathworks.com/help/fuzzy/fcm.html Документация пакета MATLAB, функция fcm], последнее обращение 15.10.2016&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Реализация алгоритма на POSTGRESQL &amp;lt;ref&amp;gt;[http://num-meth.srcc.msu.ru/zhurnal/tom_2012/pdf/v13r207.pdf Реализация алгоритма Fuzzy C-means на POSTGRESQL], последнее обращение 15.10.2016&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&lt;br /&gt;
[[en:Parallel Fuzzy c-Means Clustering]]&lt;/div&gt;</summary>
		<author><name>Coctic</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Nikmedoed&amp;diff=17852</id>
		<title>Обсуждение участника:Nikmedoed</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Nikmedoed&amp;diff=17852"/>
		<updated>2016-11-17T07:27:11Z</updated>

		<summary type="html">&lt;p&gt;Coctic: /* Статья Участник:Nikmedoed/Нечеткий алгоритм С-средних (Fuzzy C-means) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Статья [[Участник:Nikmedoed/Нечеткий алгоритм С-средних (Fuzzy C-means)]] =&lt;br /&gt;
* не указан вклад каждого автора [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:01, 25 октября 2016 (MSK)&lt;br /&gt;
** Могли бы вы подсказать в каком формате это сделать? Просто общее сообщение, либо в каждом пункте указать?&lt;br /&gt;
*** В начале написать &amp;quot;Авторы: Автор1 - раздел 1, Автор2 - раздел 2&amp;quot;. Ну или что-то в том духе. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 18:01, 28 октября 2016 (MSK)&lt;br /&gt;
:::: Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:32, 31 октября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
* п. 1.2 приведен набор формул, однако отсутствует пояснения, как эти формулы складываются в алгоритм [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:01, 25 октября 2016 (MSK)&lt;br /&gt;
** П. 1.2 расширен в соответствии с замечанием. Ожидаю отзыв. [[Участник:Illusive_mike|Дворецкий М.С.]] ([[Обсуждение участника:Illusive_mike|обсуждение]]) 15:46, 25 октября 2016 (MSK)&lt;br /&gt;
::: Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:32, 31 октября 2016 (MSK)&lt;br /&gt;
----------------&lt;br /&gt;
* п. 2.4. проведены исследования масштабируемости одной итерации. Исследование масштабируемости реализации в целом отсутствует [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:27, 17 ноября 2016 (MSK)&lt;br /&gt;
* п. 2.4. Рис. 2 приведен график зависимости эффективности от параметров задачи. Не указано, о каком виде эффективности идет речь. Значение эффективности в 100% в реальности встречается очень редко, надо в тексте пояснить, почему такой хороший результат. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:27, 17 ноября 2016 (MSK)&lt;br /&gt;
* п. 2.4. &#039;&#039;Для большинства экспериментов эффективность находится в пределах 100±3%.&#039;&#039;. Как эффективность может быть больше 100%? [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:27, 17 ноября 2016 (MSK)&lt;/div&gt;</summary>
		<author><name>Coctic</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:Demon_smd/%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=17733</id>
		<title>Участник:Demon smd/Нечеткий алгоритм С средних</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:Demon_smd/%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=17733"/>
		<updated>2016-11-16T15:28:41Z</updated>

		<summary type="html">&lt;p&gt;Coctic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Нечеткий алгоритм C средних (Fuzzy C-means)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(C^2*N*D*IterNumber)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(\log_{2}C^4*|X|^3) * IterNumber&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(C^2*|X|)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;|X|*p&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; - размерность входных векторов&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;|X|*C &amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы описания алгоритма: &lt;br /&gt;
[[Участник:Demon smd|Д.А.Гуськов]] &lt;br /&gt;
[[Участник:marina abramenkova|М.А.Абраменкова]]&lt;br /&gt;
Во все разделы вклад равноценный.&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
Нечёткий алгоритм кластеризации С-средних был разработан (для случая m=2) J.C. Dunn в 1973 г. &lt;br /&gt;
&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; &lt;br /&gt;
и усовершенствован (для случая m&amp;gt;1) &lt;br /&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;
. В отличие от алгоритма c-means данный метод кластеризации предполагает, что входные данные могут принадлежать более, чем одному кластеру одновременно.&lt;br /&gt;
Алгоритм получает на вход набор кластеризуемых векторов, количество кластеров, коэффициент неопределённости m и коэффициент &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;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;
=== Математическое описание алгоритма ===&lt;br /&gt;
Нечеткий алгоритм С средних минимизирует величину:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
J_{m} = \sum_{i = 1}^{N}\sum_{j = 1}^{C}u_{i,j}^m\left\Vert{x_{i}-c_{j}}\right\|^2 &amp;amp; , &amp;amp; &amp;amp;  1 \le m \le \infty , \\&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где m - это действительное число не меньше единицы, &amp;lt;math&amp;gt;u_{i,j}&amp;lt;/math&amp;gt; - коэффициент принадлежности вектора &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; к кластеру &amp;lt;math&amp;gt;c_{j}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; - &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый компонент &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;-мерного вектора &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;c_{j}&amp;lt;/math&amp;gt;&lt;br /&gt;
- центр &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-ого кластера, а &amp;lt;math&amp;gt;\left\Vert{*}\right\|&amp;lt;/math&amp;gt; - это любая норма, определяющая расстояние от вектора до центра кластера.&lt;br /&gt;
Нечёткое разбиение входных данных на кластеры производится итеративной оптимизацией вышеуказанной функции с обновлением коэффициента принадлежности &amp;lt;math&amp;gt;u_{i,j}&amp;lt;/math&amp;gt; и переопределением центра кластера &amp;lt;math&amp;gt;c_{j}&amp;lt;/math&amp;gt; на каждой итерации алгоритма.&lt;br /&gt;
&lt;br /&gt;
==== Вычисляемые данные на каждой итерации ====&lt;br /&gt;
* Центры кластеров рассчитываются по следующей формуле: &amp;lt;math&amp;gt;c_{j} = {{\sum_{i = 1}^{n}{u_{i,j}^m} * x_{i}} \over {\sum_{i = 1}^{n}{u_{i,j}^m}}}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;u_{i,j}&amp;lt;/math&amp;gt; — коэффициент принадлежности &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; вектора к кластеру &amp;lt;math&amp;gt;c_{j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* Коэффициент принадлежности рассчитывается по формуле: &amp;lt;math&amp;gt;u_{i,j} = {1 \over \sum_{k = 1}^{C}{({\left\Vert{x_{i}-c_{j}}\right\| \over \left\Vert{x_{i}-c_{k}}\right\|})}^{2 \over m-1}}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Решающая функция рассчитывается по формуле: &amp;lt;math&amp;gt;\max_{i,j}(|u_{i,j}^{(k)} - u_{i,j}^{(k-1)}|)&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;
&lt;br /&gt;
Ядром алгоритма является:&lt;br /&gt;
* вычисление новых центров кластеров&lt;br /&gt;
* для каждого входного вектора вычисление Евклидова расстояния до центров кластеров, а также коэффициента принадлежности кластерам&lt;br /&gt;
* вычисление решающей функции&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
В каждой итерации алгоритма происходит 3 основных действия описанных в п. 1.2.1:&lt;br /&gt;
*вычисление центров кластеров&lt;br /&gt;
*вычисление коэффициентов принадлежности&lt;br /&gt;
*вычисление решающей функции&lt;br /&gt;
Подробное описание макроструктур в виде кода приведено в пункте 1.5&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Схему реализации последовательного алгоритма можно описать на C++ следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
FCM (X[], C, m, eps){&lt;br /&gt;
    float deside = 0;&lt;br /&gt;
    float newDeside = 0;&lt;br /&gt;
    generateMembershipDegree();            //заполняет uPrev[][] случайными нормрованными коэффициентами&lt;br /&gt;
    while (true){&lt;br /&gt;
        newDeside = deside;&lt;br /&gt;
&lt;br /&gt;
        //вычисление центров кластеров&lt;br /&gt;
        for (int j=0; j&amp;lt;C; j++){           //для каждого кластера&lt;br /&gt;
            float numerator = 0;&lt;br /&gt;
            float denumerator = 0;&lt;br /&gt;
            for (int i=0; i&amp;lt;X.size(); i++){        //для каждого вектора&lt;br /&gt;
                numerator+=pow(u[i][j], m) * x[i];&lt;br /&gt;
                denumerator+=pow(u[i][j], m);&lt;br /&gt;
            }&lt;br /&gt;
            c[j] = numerator / denumerator;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        //вычисление коэффициентов u[][]&lt;br /&gt;
        for (int i=0; i&amp;lt;X.size(); i++)    //для каждого вектора&lt;br /&gt;
            for (int j=0; j&amp;lt;C; j++){   //для каждого кластера&lt;br /&gt;
                sum = 0;&lt;br /&gt;
                for (int k=0; k&amp;lt;C; k++)&lt;br /&gt;
                    sum+= pow( dist(x[i], c[j]) / dist(x[i], c[k]), 2/(m-1));&lt;br /&gt;
                u[i][j] = 1/sum&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
        //определения максимального различия между u[][] и uPrev[][]&lt;br /&gt;
        float max = 0;&lt;br /&gt;
        for (int i=0; i&amp;lt;X.size(); i++)    //для каждого вектора&lt;br /&gt;
            for (int j=0; j&amp;lt;C; j++){   //для каждого кластера&lt;br /&gt;
                if (abs(uPrev[i][j]-u[i][j])&amp;gt;max)&lt;br /&gt;
                    max = abs(uPrev[i][j]-u[i][j]);&lt;br /&gt;
&lt;br /&gt;
        if (eps &amp;lt;= max)&lt;br /&gt;
            for (int i=0; i&amp;lt;X.size(); i++)    //для каждого вектора&lt;br /&gt;
                for (int j=0; j&amp;lt;C; j++){   //для каждого кластера&lt;br /&gt;
                    uPrev[i][j]=u[i][j];&lt;br /&gt;
        else&lt;br /&gt;
            break;&lt;br /&gt;
             &lt;br /&gt;
    }&lt;br /&gt;
    return u;&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;
* параметра &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;&lt;br /&gt;
* набора входных векторов &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;&lt;br /&gt;
* выбора начальных коэффициентов &amp;lt;math&amp;gt;u&amp;lt;/math&amp;gt;&lt;br /&gt;
то в данном пункте будет приведена сложность одной итерации относительно количества входных векторов.&lt;br /&gt;
Как видно из предыдущего пункта, для вычисления центров кластеров требуется &amp;lt;math&amp;gt;O(2*C*|X|)&amp;lt;/math&amp;gt; операций, для определения коэффициентов &amp;lt;math&amp;gt;u&amp;lt;/math&amp;gt; - &amp;lt;math&amp;gt;O(C^2*|X|)&amp;lt;/math&amp;gt; операций, а для вычисления решающей функции - &amp;lt;math&amp;gt;O(2*C*|X|)&amp;lt;/math&amp;gt; операций, где &amp;lt;math&amp;gt;|X|&amp;lt;/math&amp;gt; -  число входных векторов, а &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; - количество кластеров.&lt;br /&gt;
&lt;br /&gt;
Таким образом итоговая сложность одной итерации составляет &amp;lt;math&amp;gt;O(C^2*|X|)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
&lt;br /&gt;
Как видно из пункта 1.5, на каждом действии каждой итерации алгоритма все операции, выполняющиеся в цикле, не зависят друг от друга и могут быть распараллелены. Это показано на Рисунке 1.&lt;br /&gt;
&lt;br /&gt;
[[File:FCMIG.png|thumb|center|1200px|Рисунок 1. Информационный граф алгоритма. (1)-(7) - это наборы последовательных действий (например, (2) - последовательные операции деления, взятия адреса и присваивания).]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
На каждом ярусе ярусно-параллельной формы алгоритма будет располагаться конечное число элементарных операций, например, взятие адреса, сложение или возведение в степень. Информационый граф из п.1.7 изображает свёрнутую ярусно-параллельную форму алгоритма. &lt;br /&gt;
&lt;br /&gt;
Сложность алгоритма будем рассчитывать в предположении, что число вычислительных ядер стремится к бесконечности. Как видно из информационного графа, параллельная сложность вычисления центров кластеров составляет &amp;lt;math&amp;gt;O(\log_{2} C*|X|)&amp;lt;/math&amp;gt;, вычисления коэффициентов принадлежности - &amp;lt;math&amp;gt;O(\log_{2} C^2*|X|)&amp;lt;/math&amp;gt;, а вычисления решающей функции - не больше чем &amp;lt;math&amp;gt;O(\log_{2} C*|X|)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Таким образом параллельная сложность итерации алгоритма составляет &amp;lt;math&amp;gt;O(\log_{2} C^4*|X|^3)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Так как задачи, решаемые в макроструктуре алгоритма могут быть сведены к задачам вычисления суммы элементов массива и максимального элемента массива, то на &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом ярусе графа будет находиться &amp;lt;math&amp;gt;{N}\over{2^i}&amp;lt;/math&amp;gt; операции, где N - количество элементов массива.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
==== Входные данные алгоритма ====&lt;br /&gt;
* &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;|X|&amp;lt;/math&amp;gt; входных векторов длины &amp;lt;math&amp;gt;p&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;m&amp;lt;/math&amp;gt; - коэффициент неопределённости&lt;br /&gt;
* &amp;lt;math&amp;gt;\varepsilon &amp;gt; 0&amp;lt;/math&amp;gt; - коэффициент, определяющий точность алгоритма.&lt;br /&gt;
&lt;br /&gt;
Объем входных данных: &amp;lt;math&amp;gt;|X|*p+3&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Выходные данные алгоритма ====&lt;br /&gt;
* &amp;lt;math&amp;gt;u&amp;lt;/math&amp;gt; - матрица принадлежности векторов кластерам&lt;br /&gt;
&lt;br /&gt;
Объем выходных данных: &amp;lt;math&amp;gt;|X|*C&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Увеличение скорости работы алгоритма при распараллеливании на бесконечном количестве процессоров составляет &amp;lt;math&amp;gt;O({{C^2*|X|}\over{\log_{2} (C^4*|X|^3)}})&amp;lt;/math&amp;gt;. Например, для разбиения 1000 элементов на 10 кластеров производительность параллельного алгоритма будет в 2315 раз больше, а на 20 кластеров - уже в 8477 раз.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
&lt;br /&gt;
Как видно из предыдущих пунктов, масштабируется данный алгоритм хорошо. С увеличением количества процессоров время работы падает, а с увеличением количества входных данных и количества кластеров - растёт. На рисунках показана масштабируемость алгоритма.&lt;br /&gt;
[[File:FCMCOMP1.jpg|thumb|center|1500px|Рисунок 2. Масштабируемость алгоритма. Зависимость сложности алгоритма от количества процессоров и входных данных при фиксированном количестве кластеров.]]&lt;br /&gt;
[[File:FCMCOMP2.jpg|thumb|center|1500px|Рисунок 3. Масштабируемость алгоритма. Зависимость сложности алгоритма от количества процессоров и кластеров при фиксированном количестве входных данных.]]&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Существует множество реализаций данного алгоритма. Рассмотрим некоторые из них:&lt;br /&gt;
&lt;br /&gt;
- Например, тут: https://habrahabr.ru/post/208496/&lt;br /&gt;
&amp;lt;ref&amp;gt;Нестер А. &amp;quot;Алгоритм нечёткой кластеризации fuzzy c-means на PHP&amp;quot;. [html](https://habrahabr.ru/post/208496/)&amp;lt;/ref&amp;gt;&lt;br /&gt;
приведено краткое описание алгоритма и приведена его реализация на php. В данной статье довольно подробно расписан каждый шаг алгоритма и приведён соответствующий ему фрагмент кода.&lt;br /&gt;
&lt;br /&gt;
- Тут: http://num-meth.srcc.msu.ru/zhurnal/tom_2012/v13r207.html&lt;br /&gt;
&amp;lt;ref&amp;gt;Миниахметов Р.М., Цымблер М.Л. &amp;quot;Интеграция алгоритма кластеризации Fuzzy c-Means в PostgreSQL&amp;quot;. [html](http://num-meth.srcc.msu.ru/zhurnal/tom_2012/v13r207.html)&amp;lt;/ref&amp;gt;&lt;br /&gt;
приводится реализация алгоритма для PostgreSQL, а также прилагается скрипт внедрения алгоритма.&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;/div&gt;</summary>
		<author><name>Coctic</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Demon_smd&amp;diff=17732</id>
		<title>Обсуждение участника:Demon smd</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Demon_smd&amp;diff=17732"/>
		<updated>2016-11-16T15:28:29Z</updated>

		<summary type="html">&lt;p&gt;Coctic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Статья [[Нечеткий алгоритм С средних]] =&lt;br /&gt;
* не указан вклад каждого автора [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:58, 25 октября 2016 (MSK) - исправлено&lt;br /&gt;
:: Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:29, 31 октября 2016 (MSK)&lt;br /&gt;
* п. 1.9 не приведены оценки объема входных и выходных данных [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 12:58, 25 октября 2016 (MSK) - исправлено&lt;br /&gt;
:: Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:29, 31 октября 2016 (MSK)&lt;br /&gt;
* п. 2.4. Не приведена ссылка на текст исследуемой программы [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 18:28, 16 ноября 2016 (MSK)&lt;br /&gt;
* п. 2.4. Не указана аппаратная платформа, на которой проводилось тестирование [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 18:28, 16 ноября 2016 (MSK)&lt;br /&gt;
* п. 2.4. На рис. 2 и 3 подпись вертикальной оси накладывается на подписи шкалы  [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 18:28, 16 ноября 2016 (MSK)&lt;br /&gt;
* п. 2.4. Не приведено никаких сведений о масштабируемости исследуемой программы. На рис. 2 и 3 приведены графики зависимости некоей &amp;quot;сложности&amp;quot; (какя сложность имеется в виду - не указано) от разных параметров. Как из этих графиков извлечь сведения о масштабируемости - не указано. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 18:28, 16 ноября 2016 (MSK)&lt;/div&gt;</summary>
		<author><name>Coctic</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Darel&amp;diff=17704</id>
		<title>Обсуждение участника:Darel</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Darel&amp;diff=17704"/>
		<updated>2016-11-16T13:55:33Z</updated>

		<summary type="html">&lt;p&gt;Coctic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Статья [[Участник:Ян-Мартин Тамм/Строгий алгоритм С средних]] =&lt;br /&gt;
* Отсутствует указание автора [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:17, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:58, 31 октября 2016 (MSK)&lt;br /&gt;
* Пропущен пункт 1.1 &amp;quot;общее описание алгоритма&amp;quot;, у следующих пунктов сместилась нумерация [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:17, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:58, 31 октября 2016 (MSK)&lt;br /&gt;
* п. 1.6 на рисунках приведены схема алгоритма и его блока, информационного графа не приведено [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:17, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:58, 31 октября 2016 (MSK)&lt;br /&gt;
----------------------&lt;br /&gt;
* Названия частей 1 и 2 не соответствуют шаблону [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:58, 31 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:02, 8 ноября 2016 (MSK)&lt;br /&gt;
* В списке литературы у первой ссылки отсутствуют выходные данные, по которым можно однозначно идентифицировать источник [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:17, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:02, 8 ноября 2016 (MSK)&lt;br /&gt;
* Отсутствует п. 2.4. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 16:55, 16 ноября 2016 (MSK)&lt;/div&gt;</summary>
		<author><name>Coctic</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:%D0%AF%D0%BD-%D0%9C%D0%B0%D1%80%D1%82%D0%B8%D0%BD_%D0%A2%D0%B0%D0%BC%D0%BC/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%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=17703</id>
		<title>Участник:Ян-Мартин Тамм/Строгий алгоритм С средних</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:%D0%AF%D0%BD-%D0%9C%D0%B0%D1%80%D1%82%D0%B8%D0%BD_%D0%A2%D0%B0%D0%BC%D0%BC/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%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=17703"/>
		<updated>2016-11-16T13:55:13Z</updated>

		<summary type="html">&lt;p&gt;Coctic: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Строгий алгоритм С средних (K-means, Hard C-Means)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(nkdi)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(log_2(k)log_2(d)i)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(nkd)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;nd+1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;nk&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
Автор: [[Участник:Darel|Ян-Мартин Тамм]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритма =&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&amp;lt;b&amp;gt;Строгий алгоритм C средних&amp;lt;/b&amp;gt;, более известный как &amp;lt;b&amp;gt;K-средних&amp;lt;/b&amp;gt;, решает задачу разделения векторов в многомерном пространстве на заданное количество кластеров. При этом каждый вектор принадлежит только одному кластеру, поэтому алгоритм называется строгим, в то время как нечеткий алгоритм C средних (Fuzzy C-means, Soft K-means) определяет степень принадлежности вектора каждому из кластеров.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Данная задача является NP-трудной, тем не менее описываемый алгоритм сходится к локальному оптимуму. Глобальный оптимум не гарантируется и зависит от первоначального распределения центров кластеров и их количества. &amp;lt;br&amp;gt;Общая идея алгоритма такова: фиксируем число кластеров &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;, произвольным образом выбираем центры кластеров, после чего повторяем следующие два действия, пока не будет выполнено условие остановки:&lt;br /&gt;
#Распределяем каждый вектор в ближайший кластер&lt;br /&gt;
#Пересчитываем значения центров как среднее значение координат векторов в каждом кластере&lt;br /&gt;
Минимизируется сумма расстояний векторов от центров их кластеров. Остановка производится если либо значение данной функции становится ниже некоторого порога, либо мало изменяется по сравнению с предыдущей итерацией.&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Дано множество d-мерных векторов &amp;amp;nbsp;&amp;lt;math&amp;gt;U=\{u_1, u_2, ..., u_n\}&amp;lt;/math&amp;gt; и число кластеров &amp;lt;math&amp;gt;k \in \mathbb{N}&amp;lt;/math&amp;gt;. Требуется разбить множество &amp;lt;math&amp;gt;U&amp;lt;/math&amp;gt; на &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; непересекающихся непустых кластеров &amp;lt;math&amp;gt;C_1, C_2, ..., C_k&amp;lt;/math&amp;gt; таких, что &amp;lt;math&amp;gt;{\bigcup \limits _{i = 1}^k C_i} = U &amp;lt;/math&amp;gt;. &lt;br /&gt;
&amp;lt;br&amp;gt;Для этого минимизируется функция &amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^k J_i = \sum\limits_{i=1}^k \sum\limits_{ u \in C_i} \|u-c_i \|^2 &lt;br /&gt;
&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;c_i&amp;lt;/math&amp;gt;— центр масс векторов кластера &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Произвольным образом инициализируем центры кластеров &amp;lt;math&amp;gt;c_1, c_2, ..., c_k&amp;lt;/math&amp;gt;, после чего начинается основная часть алгоритма.&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&amp;lt;li&amp;gt;Каждый вектор &amp;lt;math&amp;gt;u_l&amp;lt;/math&amp;gt; определяем в ближайший к нему кластер &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt;, то есть такой, что &lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\|u_l-c_i\|^2 \leqslant \|u_l-c_j\|^2 \;\; \forall i \neq j; \;\; (i,j=1,2,\ldots,k, \; l = 1,2,\ldots,n)&lt;br /&gt;
&amp;lt;/math&amp;gt;.&amp;lt;/li&amp;gt; Хранить информацию о принадлежности векторов кластерам будем в матрице &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; следующего вида:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ij} = \begin{cases}&lt;br /&gt;
1, &amp;amp; u_j \in C_i \\&lt;br /&gt;
0, &amp;amp; \text{otherwise}&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Считаем значение функции &amp;lt;math&amp;gt;J&amp;lt;/math&amp;gt; и прекращаем работу алгоритма, если это значение меньше заданного порога &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;, либо значение мало изменилось после текущей итерации.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Обновляем значения центров кластеров&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{u \in C_i} u \;\; (i=1,2,\ldots,k)&lt;br /&gt;
&amp;lt;/math&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;Возвращаемся к распределению векторов по кластерам.&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительным ядром алгоритма является весь алгоритм, а именно два основных его шага:&lt;br /&gt;
&amp;lt;ul&amp;gt;&amp;lt;li&amp;gt;Распределение векторов по кластерам&amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;Пересчёт центров кластеров&amp;lt;/li&amp;gt;&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как уже говорилось раньше, первоначальное распределение векторов по кластерам может быть произвольным, например, можно случайным образом выбрать &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; векторов из множества всех векторов &amp;lt;math&amp;gt;U&amp;lt;/math&amp;gt;.&amp;lt;br&amp;gt;&lt;br /&gt;
Далее начинается цикл, его первая операция — распределение векторов по кластерам. В ней для каждого вектора считается расстояние от него, до каждого кластера &amp;lt;math&amp;gt;\rho = \big \| u - c \big \|^2=\sum_{i=1}^d (u_i-c_i)^2&amp;lt;/math&amp;gt;, после чего из них выбирается наименьшее и заносится в матрицу.&amp;lt;br&amp;gt;Подсчёт функции &amp;lt;math&amp;gt;J&amp;lt;/math&amp;gt; можно проводить одновременно с первым шагом, так как в ней суммируются те же самые расстояния.&amp;lt;br&amp;gt;Пересчёт центров кластеров — сумма всех векторов кластера, делённая на количество объектов в кластере. &amp;lt;math&amp;gt;&lt;br /&gt;
c = \frac{1}{|C|} \sum\limits_{u \in C} u&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
def kmeans(points, k, cutoff):&lt;br /&gt;
    &lt;br /&gt;
    # Pick out k random points to use as our initial centroids&lt;br /&gt;
    initial = random.sample(points, k)&lt;br /&gt;
    &lt;br /&gt;
    # Create k clusters using those centroids&lt;br /&gt;
    clusters = [Cluster([p]) for p in initial]&lt;br /&gt;
    &lt;br /&gt;
    # Loop through the dataset until the clusters stabilize&lt;br /&gt;
    while True:&lt;br /&gt;
        # Create a list of lists to hold the points in each cluster&lt;br /&gt;
        lists = [ [] for c in clusters]&lt;br /&gt;
&lt;br /&gt;
        # For every point in the dataset ...&lt;br /&gt;
        for p in points:&lt;br /&gt;
            # Get the distance between that point and the centroid of the first cluster.&lt;br /&gt;
            smallest_distance = getDistance(p, clusters[0].centroid)&lt;br /&gt;
        &lt;br /&gt;
            # Set the cluster this point belongs to&lt;br /&gt;
            clusterIndex = 0&lt;br /&gt;
        &lt;br /&gt;
            # For the remainder of the clusters ...&lt;br /&gt;
            for i in range(clusterCount - 1):&lt;br /&gt;
                # calculate the distance of that point to each other cluster&#039;s centroid&lt;br /&gt;
                distance = getDistance(p, clusters[i+1].centroid)&lt;br /&gt;
                # If it&#039;s closer to that cluster&#039;s centroid update what we&lt;br /&gt;
                # think the smallest distance is, and set the point to belong to that cluster&lt;br /&gt;
                if distance &amp;lt; smallest_distance:&lt;br /&gt;
                    smallest_distance = distance&lt;br /&gt;
                    clusterIndex = i+1&lt;br /&gt;
            lists[clusterIndex].append(p)&lt;br /&gt;
        &lt;br /&gt;
        # Set our total_shift to zero for this iteration&lt;br /&gt;
        total_shift = 0.0&lt;br /&gt;
        &lt;br /&gt;
        # As many times as there are clusters ...&lt;br /&gt;
        for i in range(k):&lt;br /&gt;
            # Calculate how far the centroid moved in this iteration&lt;br /&gt;
            shift = clusters[i].update(lists[i])&lt;br /&gt;
            # Keep track of the total moves from all cluster centroid updates&lt;br /&gt;
            total_shift += shift&lt;br /&gt;
        &lt;br /&gt;
        # If the centroids have stopped moving much, we&#039;re done!&lt;br /&gt;
        if total_shift &amp;lt; cutoff:&lt;br /&gt;
            break&lt;br /&gt;
    return clusters&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Распределение по кластерам — для каждого из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов и каждого из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; кластеров посчитать расстояние, сложив &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; раз значения, на вычисление каждого из которых нужно 2 операции —&amp;amp;nbsp;&amp;lt;math&amp;gt;O(nkd)&amp;lt;/math&amp;gt;. Пересчёт центров — &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; раз сложить и &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; раз поделить — &amp;amp;nbsp;&amp;lt;math&amp;gt;O(n+k)&amp;lt;/math&amp;gt;. На завершение алгоритма понадобится &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; итераций. Итого сложность &amp;lt;math&amp;gt;O(nkdi)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
На рисунке ниже приведён информационный граф алгоритма.&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:HCM graph1.png]]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Блок, определяющий ближайший кластер, подробнее.&amp;lt;br&amp;gt;&lt;br /&gt;
[[Файл:HCM_dist1.png]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Самой трудоёмкой операцией является распределение по кластерам. Так, для рассчёта расстояний, можно провести суммирование &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; элементов за &amp;lt;math&amp;gt;log_2(d)&amp;lt;/math&amp;gt; операций. Расстояние от данного вектора до всех кластеров можно найти за одну операцию, после чего нужно найти наименьшее значение из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; элементов за &amp;lt;math&amp;gt;log_2(k)&amp;lt;/math&amp;gt; операций. И всё это нужно сделать для &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов, что можно сделать параллельно за одну операцию. Для сходимости всё так же потребуется &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; итераций, общая сложность получается &amp;lt;math&amp;gt;O(log_2(k)log_2(d)i)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; &lt;br /&gt;
*&amp;lt;math&amp;gt;U=\{u_1, u_2, ..., u_n\} \subset \mathbb{R}^d&amp;lt;/math&amp;gt; — множество векторов&lt;br /&gt;
*&amp;lt;math&amp;gt;k \in \mathbb{N}&amp;lt;/math&amp;gt; — количество кластеров&lt;br /&gt;
*&amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; — порог остановки &#039;&#039;(не обязательно)&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;nd+1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
*&amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; — матрица принадлежности векторов кластерам размера &amp;lt;math&amp;gt;nk&amp;lt;/math&amp;gt;. При этом данная матрица содержит только &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; единиц, остальные значения ноль. Возможен вывод в другом виде, например, список списков.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;nk&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&amp;lt;ul&amp;gt;&amp;lt;li&amp;gt;Алгоритм не является детерминированным, так как инициализация кластеров происходит случайным образом, однако, ничто не мешает проводить инициализацию согласно некоторому детерминированному правилу.&lt;br /&gt;
&amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;Алгоритм находит локальный оптимум, поэтому его обычно запускают несколько раз и выбирают лучший результат.&amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;Вычислительная мощность &amp;lt;math&amp;gt;\frac{kdi}{k+d}&amp;lt;/math&amp;gt;&amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;Алгоритм является устойчивым при одинаковой первоначальной инициализации — малая ошибка в начальных данных или при вычислениях очень незначительно повлияют на результат (скорее всего никак не повлияют). Тем не менее, при случайной инициализации результаты будут различны.&amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;Прост в реализации и вычислениях&amp;lt;/li&amp;gt;&amp;lt;/ul&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;
* [http://scikit-learn.org/ scikit-learn] библиотека машинного обучения для языка Python.&lt;br /&gt;
* [https://www.scipy.org/ SciPy] библиотека на языке Python, содержащая большое число реализаций различных алгоритмов.&lt;br /&gt;
* [http://elki.dbs.ifi.lmu.de ELKI] библиотека для анализа данных на языке программирования Java, содержит различные алгоритмы кластеризации.&lt;br /&gt;
* [http://spark.apache.org/ Spark] распределённая версия алгоритма.&lt;br /&gt;
* [http://mlpack.org MLPACK] библиотека машинного обучения для C++.&lt;br /&gt;
* [http://opencv.org/ OpenCV] библиотека содержит реализацию алгоритма.&lt;br /&gt;
* [http://mahout.apache.org Apache Mahout] содержит реализацию алгоритма на базе MapReduce.&lt;br /&gt;
* [http://www.cs.waikato.ac.nz/~ml/weka Weka] библиотека и инструмент для анализа данных на языке Java.&lt;br /&gt;
* [http://torch.ch/ Torch] библиотека машинного обучения на базе языка программирования Lua.&lt;br /&gt;
* [http://www.accord-framework.net/ Accord.NET] содержит несколько различных реализаций на языке C#.&lt;br /&gt;
* [https://www.r-bloggers.com/k-means-clustering-in-r/ R k-means] реализация на языке R.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&amp;lt;ol&amp;gt;&amp;lt;li&amp;gt;[http://faculty.petra.ac.id/resmana/private/fuzzy/nfmod.pdf Jan Jantzen «Neurofuzzy Modelling».(Электронное издание)] Technical University of Denmark, Department of Automation, Bldg 326, DK-2800 Lyngby, DENMARK.&lt;br /&gt;
Tech. report no 98-H-874 (nfmod), 30 Oct 1998. &amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;Steinhaus H. (1956). Sur la division des corps materiels en parties. Bull. Acad. Polon. Sci., C1. III vol IV: 801—804.&amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;Lloyd S. (1957). Least square quantization in PCM’s. Bell Telephone Laboratories Paper.&amp;lt;/li&amp;gt;&amp;lt;li&amp;gt;MacQueen J. (1967). Some methods for classification and analysis of multivariate observations. In Proc. 5th Berkeley Symp. on Math. Statistics and Probability, pages 281—297.&amp;lt;/li&amp;gt;&amp;lt;/ol&amp;gt;&lt;/div&gt;</summary>
		<author><name>Coctic</name></author>
	</entry>
</feed>