<?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=Protsenko</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=Protsenko"/>
	<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/Protsenko"/>
	<updated>2026-10-22T19:06:27Z</updated>
	<subtitle>Вклад</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<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:Protsenko&amp;diff=21445</id>
		<title>Обсуждение участника:Protsenko</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:Protsenko&amp;diff=21445"/>
		<updated>2016-12-19T23:54:54Z</updated>

		<summary type="html">&lt;p&gt;Protsenko: /* Замечания по тексту */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Статья [[Участник:ADovganich/Нечеткий алгоритм С средних]] ==&lt;br /&gt;
&lt;br /&gt;
=== Замечания по тексту ===&lt;br /&gt;
&lt;br /&gt;
* 1.8 — Непонятна схема распараллеливания для такой оценки сложности. У вас C*K процессов? [[Участник:Chalker|Chalker]] ([[Обсуждение участника:Chalker|обсуждение]]) 22:43, 17 декабря 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
В самом лучшем случае, для вычисления суммы n чисел нам потребуется выполнить &amp;lt;math&amp;gt;\log_{2} &amp;lt;/math&amp;gt;сложений. (Каскадная схема). Это описан самый быстрый из существующих способ.&lt;br /&gt;
&lt;br /&gt;
В MPI используем K процессов (так как количество процессов ограничено, то на один процесс может выделяться больше одного вектора) и каждый процесс по отдельности обрабатывает свои вектора с использование OpenMP.&lt;br /&gt;
&lt;br /&gt;
* 1.8 — Даже эту формулу можно записать проще по тривиальным свойствам логарифма. [[Участник:Chalker|Chalker]] ([[Обсуждение участника:Chalker|обсуждение]]) 22:43, 17 декабря 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
Данная формула была приведена в таком виде что бы показать соотношение влияния количества кластеров и количества векторов на сложность алгоритма. Можем упростить ее, если так лучше.&lt;br /&gt;
&lt;br /&gt;
* 1.8 — Схема распараллеливания должна быть описана более детально. [[Участник:Chalker|Chalker]] ([[Обсуждение участника:Chalker|обсуждение]]) 22:43, 17 декабря 2016 (MSK)&lt;br /&gt;
 &lt;br /&gt;
Описали схему подробнее.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Сложность не зависит от N? В оценке сложности не учтена размерность входных векторов. [[Участник:Chalker|Chalker]] ([[Обсуждение участника:Chalker|обсуждение]]) 20:14, 17 декабря 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
Исправлено.&lt;br /&gt;
&lt;br /&gt;
* 1.6 — в терминах каких операций измеряется сложность? [[Участник:Chalker|Chalker]] ([[Обсуждение участника:Chalker|обсуждение]]) 20:14, 17 декабря 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
Подсчитаны операции умножения и деления.&lt;br /&gt;
В разделе &amp;quot;вычисление центров кластеров&amp;quot; будет C*K умножений для вычисления числителя. (Деление числителя на знаменатель будет выполняться С раз, что на порядок меньше).&lt;br /&gt;
Для раздела &amp;quot;вычисление решающей функции&amp;quot; посчитано количество умножений C*K раз. (Деления в этом разделе нет)&lt;br /&gt;
Для обновления матрицы посчитано количество операций деления С*C*K (Порядок у деления m[i,k]=1/m[i,k] ниже)&lt;br /&gt;
&lt;br /&gt;
* 2.4 — я не совсем понимаю, на какой именно конфигурации выполнялся анализ масштабируемости. Там написано, что используется OpenMP (для систем с общей памятью), суперкомпьютер Ломоносов, а количество процессоров доходит до 120. Я не вижу таких узлов в Ломоносове в его описании [http://parallel.ru/cluster/lomonosov.html]. Можете пояснить? [[Участник:Chalker|Chalker]] ([[Обсуждение участника:Chalker|обсуждение]]) 18:31, 5 декабря 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
Запускали в тестовой очереди. В тексте допустили неточность, для передачи данных данных использовали MPI. Запустили еще раз, номер node1-130-[01-16]. 120- количество потоков.&lt;br /&gt;
&lt;br /&gt;
** Текст до сих пор не исправлен, в приведённой реализации тоже используется OpenMP, а не MPI. Если используется она — то это запускается на одном узле. Данные точно верны? [[Участник:Chalker|Chalker]] ([[Обсуждение участника:Chalker|обсуждение]]) 20:14, 17 декабря 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
Исправили текст.&lt;br /&gt;
В MPI используем K процессов (так как количество процессов ограничено, то на один процесс может выделяться больше одного вектора) и каждый процесс по отдельности обрабатывает свои вектора с использование OpenMP.&lt;br /&gt;
В зависимости от номера процесса определяется какие вектора он будет обрабатывать. Каждый процесс обрабатывает свои вектора, а потом собирается общий результат.&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
* В разделе 1.5  кроме текста программы нужны словесные пояснения. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 16:38, 27 октября 2016 (MSK)&lt;br /&gt;
* Граф, представленный в разделе 1.7, не является информационным графом (ациклический граф, вершины - операции, дуги - информационные зависимости). [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 16:38, 27 октября 2016 (MSK)&lt;br /&gt;
** Приведённый граф по-прежнему является графом управления, а не информационным графом: содержит цикл, ветвление и т.д. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 11:31, 1 ноября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
* В разделе 1.9 требуется привести оценки объёма входных и выходных данных. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 16:38, 27 октября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
* Подписи к рисунку в разделе 2.4 крайне мелкие, почти неразличимые. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 15:19, 16 ноября 2016 (MSK)&lt;br /&gt;
* В разделе 2.4 не приведены все параметры запуска теста - какой компилятор, с какими опциями использовался, какие версии библиотек, на каких узлах проводился запуск и т.д. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 15:19, 16 ноября 2016 (MSK) &lt;br /&gt;
* В разделе 2.4 не приведена использованная в экспериментах реализация алгоритма. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 15:19, 16 ноября 2016 (MSK) &lt;br /&gt;
* Рисунки в статье не пронумерованы. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 14:04, 21 ноября 2016 (MSK) &lt;br /&gt;
* Из графиков в разделе 2.4 следует сделать выводы о масштабируемости реализации. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 14:04, 21 ноября 2016 (MSK) &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Исправлено&lt;br /&gt;
&lt;br /&gt;
Граф исправлен еще раз&lt;/div&gt;</summary>
		<author><name>Protsenko</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:Protsenko&amp;diff=21444</id>
		<title>Обсуждение участника:Protsenko</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:Protsenko&amp;diff=21444"/>
		<updated>2016-12-19T23:54:08Z</updated>

		<summary type="html">&lt;p&gt;Protsenko: /* Статья Участник:ADovganich/Нечеткий алгоритм С средних */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Статья [[Участник:ADovganich/Нечеткий алгоритм С средних]] ==&lt;br /&gt;
&lt;br /&gt;
=== Замечания по тексту ===&lt;br /&gt;
&lt;br /&gt;
* 1.8 — Непонятна схема распараллеливания для такой оценки сложности. У вас C*K процессов? [[Участник:Chalker|Chalker]] ([[Обсуждение участника:Chalker|обсуждение]]) 22:43, 17 декабря 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
В самом лучшем случае, для вычисления суммы n чисел нам потребуется выполнить &amp;lt;math&amp;gt;log _{2} n&amp;lt;\math&amp;gt; сложений. (Каскадная схема). Это описан самый быстрый из существующих способ.&lt;br /&gt;
&lt;br /&gt;
В MPI используем K процессов (так как количество процессов ограничено, то на один процесс может выделяться больше одного вектора) и каждый процесс по отдельности обрабатывает свои вектора с использование OpenMP.&lt;br /&gt;
&lt;br /&gt;
* 1.8 — Даже эту формулу можно записать проще по тривиальным свойствам логарифма. [[Участник:Chalker|Chalker]] ([[Обсуждение участника:Chalker|обсуждение]]) 22:43, 17 декабря 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
Данная формула была приведена в таком виде что бы показать соотношение влияния количества кластеров и количества векторов на сложность алгоритма. Можем упростить ее, если так лучше.&lt;br /&gt;
&lt;br /&gt;
* 1.8 — Схема распараллеливания должна быть описана более детально. [[Участник:Chalker|Chalker]] ([[Обсуждение участника:Chalker|обсуждение]]) 22:43, 17 декабря 2016 (MSK)&lt;br /&gt;
 &lt;br /&gt;
Описали схему подробнее.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Сложность не зависит от N? В оценке сложности не учтена размерность входных векторов. [[Участник:Chalker|Chalker]] ([[Обсуждение участника:Chalker|обсуждение]]) 20:14, 17 декабря 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
Исправлено.&lt;br /&gt;
&lt;br /&gt;
* 1.6 — в терминах каких операций измеряется сложность? [[Участник:Chalker|Chalker]] ([[Обсуждение участника:Chalker|обсуждение]]) 20:14, 17 декабря 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
Подсчитаны операции умножения и деления.&lt;br /&gt;
В разделе &amp;quot;вычисление центров кластеров&amp;quot; будет C*K умножений для вычисления числителя. (Деление числителя на знаменатель будет выполняться С раз, что на порядок меньше).&lt;br /&gt;
Для раздела &amp;quot;вычисление решающей функции&amp;quot; посчитано количество умножений C*K раз. (Деления в этом разделе нет)&lt;br /&gt;
Для обновления матрицы посчитано количество операций деления С*C*K (Порядок у деления m[i,k]=1/m[i,k] ниже)&lt;br /&gt;
&lt;br /&gt;
* 2.4 — я не совсем понимаю, на какой именно конфигурации выполнялся анализ масштабируемости. Там написано, что используется OpenMP (для систем с общей памятью), суперкомпьютер Ломоносов, а количество процессоров доходит до 120. Я не вижу таких узлов в Ломоносове в его описании [http://parallel.ru/cluster/lomonosov.html]. Можете пояснить? [[Участник:Chalker|Chalker]] ([[Обсуждение участника:Chalker|обсуждение]]) 18:31, 5 декабря 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
Запускали в тестовой очереди. В тексте допустили неточность, для передачи данных данных использовали MPI. Запустили еще раз, номер node1-130-[01-16]. 120- количество потоков.&lt;br /&gt;
&lt;br /&gt;
** Текст до сих пор не исправлен, в приведённой реализации тоже используется OpenMP, а не MPI. Если используется она — то это запускается на одном узле. Данные точно верны? [[Участник:Chalker|Chalker]] ([[Обсуждение участника:Chalker|обсуждение]]) 20:14, 17 декабря 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
Исправили текст.&lt;br /&gt;
В MPI используем K процессов (так как количество процессов ограничено, то на один процесс может выделяться больше одного вектора) и каждый процесс по отдельности обрабатывает свои вектора с использование OpenMP.&lt;br /&gt;
В зависимости от номера процесса определяется какие вектора он будет обрабатывать. Каждый процесс обрабатывает свои вектора, а потом собирается общий результат.&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
* В разделе 1.5  кроме текста программы нужны словесные пояснения. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 16:38, 27 октября 2016 (MSK)&lt;br /&gt;
* Граф, представленный в разделе 1.7, не является информационным графом (ациклический граф, вершины - операции, дуги - информационные зависимости). [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 16:38, 27 октября 2016 (MSK)&lt;br /&gt;
** Приведённый граф по-прежнему является графом управления, а не информационным графом: содержит цикл, ветвление и т.д. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 11:31, 1 ноября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
* В разделе 1.9 требуется привести оценки объёма входных и выходных данных. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 16:38, 27 октября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
* Подписи к рисунку в разделе 2.4 крайне мелкие, почти неразличимые. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 15:19, 16 ноября 2016 (MSK)&lt;br /&gt;
* В разделе 2.4 не приведены все параметры запуска теста - какой компилятор, с какими опциями использовался, какие версии библиотек, на каких узлах проводился запуск и т.д. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 15:19, 16 ноября 2016 (MSK) &lt;br /&gt;
* В разделе 2.4 не приведена использованная в экспериментах реализация алгоритма. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 15:19, 16 ноября 2016 (MSK) &lt;br /&gt;
* Рисунки в статье не пронумерованы. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 14:04, 21 ноября 2016 (MSK) &lt;br /&gt;
* Из графиков в разделе 2.4 следует сделать выводы о масштабируемости реализации. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 14:04, 21 ноября 2016 (MSK) &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Исправлено&lt;br /&gt;
&lt;br /&gt;
Граф исправлен еще раз&lt;/div&gt;</summary>
		<author><name>Protsenko</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:Protsenko&amp;diff=21443</id>
		<title>Обсуждение участника:Protsenko</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:Protsenko&amp;diff=21443"/>
		<updated>2016-12-19T23:53:39Z</updated>

		<summary type="html">&lt;p&gt;Protsenko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Статья [[Участник:ADovganich/Нечеткий алгоритм С средних]] ==&lt;br /&gt;
&lt;br /&gt;
=== Замечания по тексту ===&lt;br /&gt;
&lt;br /&gt;
* 1.8 — Непонятна схема распараллеливания для такой оценки сложности. У вас C*K процессов? [[Участник:Chalker|Chalker]] ([[Обсуждение участника:Chalker|обсуждение]]) 22:43, 17 декабря 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
В самом лучшем случае, для вычисления суммы n чисел нам потребуется выполнить l &amp;lt;math&amp;gt;log _{2} n&amp;lt;\math&amp;gt; сложений. (Каскадная схема). Это описан самый быстрый из существующих способ.&lt;br /&gt;
&lt;br /&gt;
В MPI используем K процессов (так как количество процессов ограничено, то на один процесс может выделяться больше одного вектора) и каждый процесс по отдельности обрабатывает свои вектора с использование OpenMP.&lt;br /&gt;
&lt;br /&gt;
* 1.8 — Даже эту формулу можно записать проще по тривиальным свойствам логарифма. [[Участник:Chalker|Chalker]] ([[Обсуждение участника:Chalker|обсуждение]]) 22:43, 17 декабря 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
Данная формула была приведена в таком виде что бы показать соотношение влияния количества кластеров и количества векторов на сложность алгоритма. Можем упростить ее, если так лучше.&lt;br /&gt;
&lt;br /&gt;
* 1.8 — Схема распараллеливания должна быть описана более детально. [[Участник:Chalker|Chalker]] ([[Обсуждение участника:Chalker|обсуждение]]) 22:43, 17 декабря 2016 (MSK)&lt;br /&gt;
 &lt;br /&gt;
Описали схему подробнее.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Сложность не зависит от N? В оценке сложности не учтена размерность входных векторов. [[Участник:Chalker|Chalker]] ([[Обсуждение участника:Chalker|обсуждение]]) 20:14, 17 декабря 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
Исправлено.&lt;br /&gt;
&lt;br /&gt;
* 1.6 — в терминах каких операций измеряется сложность? [[Участник:Chalker|Chalker]] ([[Обсуждение участника:Chalker|обсуждение]]) 20:14, 17 декабря 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
Подсчитаны операции умножения и деления.&lt;br /&gt;
В разделе &amp;quot;вычисление центров кластеров&amp;quot; будет C*K умножений для вычисления числителя. (Деление числителя на знаменатель будет выполняться С раз, что на порядок меньше).&lt;br /&gt;
Для раздела &amp;quot;вычисление решающей функции&amp;quot; посчитано количество умножений C*K раз. (Деления в этом разделе нет)&lt;br /&gt;
Для обновления матрицы посчитано количество операций деления С*C*K (Порядок у деления m[i,k]=1/m[i,k] ниже)&lt;br /&gt;
&lt;br /&gt;
* 2.4 — я не совсем понимаю, на какой именно конфигурации выполнялся анализ масштабируемости. Там написано, что используется OpenMP (для систем с общей памятью), суперкомпьютер Ломоносов, а количество процессоров доходит до 120. Я не вижу таких узлов в Ломоносове в его описании [http://parallel.ru/cluster/lomonosov.html]. Можете пояснить? [[Участник:Chalker|Chalker]] ([[Обсуждение участника:Chalker|обсуждение]]) 18:31, 5 декабря 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
Запускали в тестовой очереди. В тексте допустили неточность, для передачи данных данных использовали MPI. Запустили еще раз, номер node1-130-[01-16]. 120- количество потоков.&lt;br /&gt;
&lt;br /&gt;
** Текст до сих пор не исправлен, в приведённой реализации тоже используется OpenMP, а не MPI. Если используется она — то это запускается на одном узле. Данные точно верны? [[Участник:Chalker|Chalker]] ([[Обсуждение участника:Chalker|обсуждение]]) 20:14, 17 декабря 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
Исправили текст.&lt;br /&gt;
В MPI используем K процессов (так как количество процессов ограничено, то на один процесс может выделяться больше одного вектора) и каждый процесс по отдельности обрабатывает свои вектора с использование OpenMP.&lt;br /&gt;
В зависимости от номера процесса определяется какие вектора он будет обрабатывать. Каждый процесс обрабатывает свои вектора, а потом собирается общий результат.&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
* В разделе 1.5  кроме текста программы нужны словесные пояснения. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 16:38, 27 октября 2016 (MSK)&lt;br /&gt;
* Граф, представленный в разделе 1.7, не является информационным графом (ациклический граф, вершины - операции, дуги - информационные зависимости). [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 16:38, 27 октября 2016 (MSK)&lt;br /&gt;
** Приведённый граф по-прежнему является графом управления, а не информационным графом: содержит цикл, ветвление и т.д. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 11:31, 1 ноября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
* В разделе 1.9 требуется привести оценки объёма входных и выходных данных. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 16:38, 27 октября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
* Подписи к рисунку в разделе 2.4 крайне мелкие, почти неразличимые. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 15:19, 16 ноября 2016 (MSK)&lt;br /&gt;
* В разделе 2.4 не приведены все параметры запуска теста - какой компилятор, с какими опциями использовался, какие версии библиотек, на каких узлах проводился запуск и т.д. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 15:19, 16 ноября 2016 (MSK) &lt;br /&gt;
* В разделе 2.4 не приведена использованная в экспериментах реализация алгоритма. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 15:19, 16 ноября 2016 (MSK) &lt;br /&gt;
* Рисунки в статье не пронумерованы. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 14:04, 21 ноября 2016 (MSK) &lt;br /&gt;
* Из графиков в разделе 2.4 следует сделать выводы о масштабируемости реализации. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 14:04, 21 ноября 2016 (MSK) &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Исправлено&lt;br /&gt;
&lt;br /&gt;
Граф исправлен еще раз&lt;/div&gt;</summary>
		<author><name>Protsenko</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:ADovganich/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=21442</id>
		<title>Участник:ADovganich/Нечеткий алгоритм С средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:ADovganich/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=21442"/>
		<updated>2016-12-19T23:52:20Z</updated>

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

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

		<summary type="html">&lt;p&gt;Protsenko: /* Замечания по тексту */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Статья [[Участник:ADovganich/Нечеткий алгоритм С средних]] ==&lt;br /&gt;
&lt;br /&gt;
=== Замечания по тексту ===&lt;br /&gt;
&lt;br /&gt;
* 2.4 — я не совсем понимаю, на какой именно конфигурации выполнялся анализ масштабируемости. Там написано, что используется OpenMP (для систем с общей памятью), суперкомпьютер Ломоносов, а количество процессоров доходит до 120. Я не вижу таких узлов в Ломоносове в его описании [http://parallel.ru/cluster/lomonosov.html]. Можете пояснить? [[Участник:Chalker|Chalker]] ([[Обсуждение участника:Chalker|обсуждение]]) 18:31, 5 декабря 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
Запускали в тестовой очереди. В тексте допустили неточность, для передачи данных данных использовали MPI. Запустили еще раз, номер node1-130-[01-16]. 120- количество потоков.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
* В разделе 1.5  кроме текста программы нужны словесные пояснения. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 16:38, 27 октября 2016 (MSK)&lt;br /&gt;
* Граф, представленный в разделе 1.7, не является информационным графом (ациклический граф, вершины - операции, дуги - информационные зависимости). [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 16:38, 27 октября 2016 (MSK)&lt;br /&gt;
** Приведённый граф по-прежнему является графом управления, а не информационным графом: содержит цикл, ветвление и т.д. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 11:31, 1 ноября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
* В разделе 1.9 требуется привести оценки объёма входных и выходных данных. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 16:38, 27 октября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
* Подписи к рисунку в разделе 2.4 крайне мелкие, почти неразличимые. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 15:19, 16 ноября 2016 (MSK)&lt;br /&gt;
* В разделе 2.4 не приведены все параметры запуска теста - какой компилятор, с какими опциями использовался, какие версии библиотек, на каких узлах проводился запуск и т.д. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 15:19, 16 ноября 2016 (MSK) &lt;br /&gt;
* В разделе 2.4 не приведена использованная в экспериментах реализация алгоритма. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 15:19, 16 ноября 2016 (MSK) &lt;br /&gt;
* Рисунки в статье не пронумерованы. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 14:04, 21 ноября 2016 (MSK) &lt;br /&gt;
* Из графиков в разделе 2.4 следует сделать выводы о масштабируемости реализации. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 14:04, 21 ноября 2016 (MSK) &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Исправлено&lt;br /&gt;
&lt;br /&gt;
Граф исправлен еще раз&lt;/div&gt;</summary>
		<author><name>Protsenko</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:ADovganich/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=19605</id>
		<title>Участник:ADovganich/Нечеткий алгоритм С средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:ADovganich/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=19605"/>
		<updated>2016-11-30T10:26:35Z</updated>

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

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

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

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

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

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

		<summary type="html">&lt;p&gt;Protsenko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Protsenko</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:ADovganich/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=18505</id>
		<title>Участник:ADovganich/Нечеткий алгоритм С средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:ADovganich/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=18505"/>
		<updated>2016-11-19T21:26:25Z</updated>

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

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

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

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

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

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

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

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

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

		<summary type="html">&lt;p&gt;Protsenko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Protsenko</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:Protsenko&amp;diff=15784</id>
		<title>Обсуждение участника:Protsenko</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:Protsenko&amp;diff=15784"/>
		<updated>2016-11-02T12:42:25Z</updated>

		<summary type="html">&lt;p&gt;Protsenko: /* Замечания по тексту */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Статья [[Участник:ADovganich/Нечеткий алгоритм С средних]] ==&lt;br /&gt;
&lt;br /&gt;
=== Замечания по тексту ===&lt;br /&gt;
* В разделе 1.5  кроме текста программы нужны словесные пояснения. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 16:38, 27 октября 2016 (MSK)&lt;br /&gt;
* Граф, представленный в разделе 1.7, не является информационным графом (ациклический граф, вершины - операции, дуги - информационные зависимости). [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 16:38, 27 октября 2016 (MSK)&lt;br /&gt;
** Приведённый граф по-прежнему является графом управления, а не информационным графом: содержит цикл, ветвление и т.д. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 11:31, 1 ноября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
* В разделе 1.9 требуется привести оценки объёма входных и выходных данных. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 16:38, 27 октября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
Исправлено&lt;br /&gt;
&lt;br /&gt;
Граф исправлен еще раз&lt;/div&gt;</summary>
		<author><name>Protsenko</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:ADovganich/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=15783</id>
		<title>Участник:ADovganich/Нечеткий алгоритм С средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:ADovganich/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=15783"/>
		<updated>2016-11-02T12:41:38Z</updated>

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

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

		<summary type="html">&lt;p&gt;Protsenko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Protsenko</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:ADovganich/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=15780</id>
		<title>Участник:ADovganich/Нечеткий алгоритм С средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:ADovganich/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=15780"/>
		<updated>2016-11-02T12:36:14Z</updated>

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

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

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

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

		<summary type="html">&lt;p&gt;Protsenko: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Protsenko</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:ADovganich/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=14736</id>
		<title>Участник:ADovganich/Нечеткий алгоритм С средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:ADovganich/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=14736"/>
		<updated>2016-10-29T18:40:48Z</updated>

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

		<summary type="html">&lt;p&gt;Protsenko: /* Статья Участник:ADovganich/Нечеткий алгоритм С средних */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Статья [[Участник:ADovganich/Нечеткий алгоритм С средних]] ==&lt;br /&gt;
&lt;br /&gt;
=== Замечания по тексту ===&lt;br /&gt;
* В разделе 1.5  кроме текста программы нужны словесные пояснения. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 16:38, 27 октября 2016 (MSK)&lt;br /&gt;
* Граф, представленный в разделе 1.7, не является информационным графом (ациклический граф, вершины - операции, дуги - информационные зависимости). [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 16:38, 27 октября 2016 (MSK)&lt;br /&gt;
* В разделе 1.9 требуется привести оценки объёма входных и выходных данных. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 16:38, 27 октября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
Исправлено&lt;/div&gt;</summary>
		<author><name>Protsenko</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:ADovganich/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=14734</id>
		<title>Участник:ADovganich/Нечеткий алгоритм С средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:ADovganich/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=14734"/>
		<updated>2016-10-29T18:38:38Z</updated>

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

		<summary type="html">&lt;p&gt;Protsenko: Protsenko загрузил новую версию Файл:Снимок экрана 2016-10-15 в 23.10.05.png&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Информационный граф алгоритма c-means&lt;/div&gt;</summary>
		<author><name>Protsenko</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:ADovganich/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=14607</id>
		<title>Участник:ADovganich/Нечеткий алгоритм С средних</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:ADovganich/%D0%9D%D0%B5%D1%87%D0%B5%D1%82%D0%BA%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85&amp;diff=14607"/>
		<updated>2016-10-28T21:48:34Z</updated>

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

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

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

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

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

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

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

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

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

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

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

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

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

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