<?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=%D0%AE%D1%80%D0%B8%D0%B9+%D0%9A%D0%BE%D0%BC%D0%B0%D1%80%D0%BE%D0%B2</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=%D0%AE%D1%80%D0%B8%D0%B9+%D0%9A%D0%BE%D0%BC%D0%B0%D1%80%D0%BE%D0%B2"/>
	<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/%D0%AE%D1%80%D0%B8%D0%B9_%D0%9A%D0%BE%D0%BC%D0%B0%D1%80%D0%BE%D0%B2"/>
	<updated>2026-10-22T20:38:50Z</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:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE&amp;diff=21348</id>
		<title>Обсуждение участника:Светлана Лукьяненко</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE&amp;diff=21348"/>
		<updated>2016-12-19T09:47:50Z</updated>

		<summary type="html">&lt;p&gt;Юрий Комаров: /* Статья Участник:Светлана Лукьяненко/Строгий алгоритм С средних (Hard C-Means, HCM) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Статья [[Участник:Светлана Лукьяненко/Строгий алгоритм С средних (Hard C-Means, HCM)]] =&lt;br /&gt;
&lt;br /&gt;
* Там действительно надо O(N*C) итераций или это какая-то оценка сверху? Откуда она взялась, кроме соображений того, что при превышении алгоритм бы был неэффективен? [[Участник:Chalker|Chalker]] ([[Обсуждение участника:Chalker|обсуждение]]) 23:22, 18 декабря 2016 (MSK)&lt;br /&gt;
** Исключительно из этих соображений, поскольку скорость сходимости алгоритма не определена. Более того, где-то в тексте было упомянуто, что к действительному минимуму он может не сходиться. [[Участник:Юрий Комаров|Комаров Юрий]]&lt;br /&gt;
** Исправлено введением числа итераций в явном виде и их включением в оценки сложности и высоты япф.&lt;br /&gt;
* Ни ширина, ни высота не зависят от размерности векторов? [[Участник:Chalker|Chalker]] ([[Обсуждение участника:Chalker|обсуждение]]) 23:15, 18 декабря 2016 (MSK)&lt;br /&gt;
** Учтено. [[Участник:Юрий Комаров|Комаров Юрий]]&lt;br /&gt;
* «получаем итоговую сложность последовательной реализации алгоритма O(nNc) {\displaystyle O(nNc)} (в предположении, что n {\displaystyle n} и C {\displaystyle C} существенно меньше N {\displaystyle N})» — что имелось ввиду? [[Участник:Chalker|Chalker]] ([[Обсуждение участника:Chalker|обсуждение]]) 23:15, 18 декабря 2016 (MSK)&lt;br /&gt;
* 1.6 — «Ожидая, что предельная точность будет достигнута менее, чем за N итераций…» — у вас получается сложность алгоритма тогда не O(N), а O(N*сложность итерации), если итераций N штук. В литературе есть какие-то оценки требуемого количества итераций исходя из входных параметров? [[Участник:Chalker|Chalker]] ([[Обсуждение участника:Chalker|обсуждение]]) 18:21, 18 декабря 2016 (MSK)&lt;br /&gt;
** нет, оценок нет, поэтому предлагается оценить через O(NC) [[Участник:Юрий Комаров|Комаров Юрий]]&lt;br /&gt;
* 1.8 — высота не равна O(1) на вашем графе, она зависит в том числе от N. [[Участник:Chalker|Chalker]] ([[Обсуждение участника:Chalker|обсуждение]]) 23:48, 17 декабря 2016 (MSK)&lt;br /&gt;
* 1.6 — сложность не равна O(N), у вас одних только операций умножения строчкой выше O(nNC). [[Участник:Chalker|Chalker]] ([[Обсуждение участника:Chalker|обсуждение]]) 23:48, 17 декабря 2016 (MSK)&lt;br /&gt;
** Согласен, O(nNC). [[Участник:Юрий Комаров|Комаров Юрий]]&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Не указан вклад каждого автора [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:57, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:05, 31 октября 2016 (MSK)&lt;br /&gt;
* Значительная часть п. 1.2  совпадает с тем же пунктом из [[Участник:Каледа Александр/Строгий алгоритм С средних (Hard C-Means)]] [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:05, 25 октября 2016 (MSK)&lt;br /&gt;
** Замечание снимается [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:05, 31 октября 2016 (MSK)&lt;br /&gt;
* В списке литературы отсутствуют выходные данные публикаций, кроме названия и автора. По приведенным данным определить конкретную публикацию не представляется возможным. Стоит добавить ссылку на оригинальную публикацию с описанием алгоритма, упомянутую в начале п.1.1 [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:57, 25 октября 2016 (MSK)&lt;br /&gt;
** Не исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:05, 31 октября 2016 (MSK)&lt;br /&gt;
* Список литературы совпадает со списком из [[Участник:Каледа Александр/Строгий алгоритм С средних (Hard C-Means)]] [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:01, 25 октября 2016 (MSK)&lt;br /&gt;
** Замечание снимается [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:05, 31 октября 2016 (MSK)&lt;br /&gt;
----------------------&lt;br /&gt;
* Комментарий от [[Участник:Юрий Комаров|Комарова Юрия]]: Сравните, пожалуйста, нашу историю работы над статьёй с историей работы над статьёй наших коллег: Каледы и его товарища. Сделав это, Вы обнаружите, что мы начали работать сразу же после выдачи задания, практически одними из первых и гораздо раньше указанных ребят, и неоднократно правили каждый из пунктов, доводя их до лучшей кондиции. За то, что пункт 1.2, как, впрочем, и другие пункты, и список литературы были составлены нами лично в процессе длительной совместной работы со [[Участник:Светлана Лукьяненко|Светланой]], отвечаю головой. Надеюсь, вопрос о плагиате больше не возникнет. В такой ситуации исправлять что-то должны явно не мы. С уважением, Комаров Юрий.&lt;br /&gt;
** В мои задачи не входить обвинять кого-то в плагиате, проводить расследования, кто у кого списал, или выяснять, кто прав, а кто нет. Меня попросили проверить статью, обращая внимание на пересечения с другими на ту же тему. В двух статьях есть общая часть, это пошло в замечания к обеим статьям. Пересечение уйдет - замечание снимется. Кто исправит текст - мне все равно. Когда в статье появится метка, что ее можно снова проверять - я сравню тексты снова. Пока текст совпадает - замечание с моей стороны остается. Есть А.С. Антонов, если он сочтет, что это замечание можно проигнорировать (в одной статье или в обеих) - он продвинет статью дальше. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 18:31, 28 октября 2016 (MSK)&lt;br /&gt;
** Если говорить о, скажем мягко, некорректном заимствовании, то ваш п 1.2 есть воспроизведение фрагмента из работы Нейского с небольшими добавлениями. У вас имеется разрешение автора на такое воспроизведение? Так что не стоит так сразу головой-то... [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 18:31, 28 октября 2016 (MSK)&lt;br /&gt;
** В общем, не стоит отвечать в таком тоне. Я могу понять возмущение, но писать надо корректнее. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 18:31, 28 октября 2016 (MSK)&lt;br /&gt;
* Вклад авторов указан, в источниках приведены ссылки. Исправлять часть статьи, которую у нас украли наши коллеги (дата создания их страницы 15 октября), должны не мы, а указанные личности. К сожалению, заставить их это сделать мы не можем, полагаю, регулирование этого вопроса нам разумнее доверить проверяющим.&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
* В списке литературы отсутствуют выходные данные публикаций, кроме названия и автора. По приведенным данным определить конкретную публикацию не представляется возможным. Стоит добавить ссылку на оригинальную публикацию с описанием алгоритма, упомянутую в начале п.1.1  [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:05, 31 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:06, 3 ноября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
* п. 2.4. Не приведена ссылка на текст анализируемой программы. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:38, 17 ноября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:28, 22 ноября 2016 (MSK)&lt;br /&gt;
* Необходимо указать характеристики программно-аппаратной платформы (какой компилятор, с какими опциями использовался, какие версии библиотек, на каких узлах проводился запуск и т.д.) [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:28, 22 ноября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:14, 23 ноября 2016 (MSK)&lt;br /&gt;
* В подписи к рис. 3 указано, что это &#039;&#039;График производительности ... от числа параллельных процессов&#039;&#039;, а подписи к оси указано, что по ней отложено число процессоров (Processors). Какой вариант правильный? [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:28, 22 ноября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:14, 23 ноября 2016 (MSK)&lt;/div&gt;</summary>
		<author><name>Юрий Комаров</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=21273</id>
		<title>Участник:Светлана Лукьяненко/Строгий алгоритм С средних (Hard C-Means, HCM)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=21273"/>
		<updated>2016-12-18T20:45:22Z</updated>

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

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

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

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

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

		<summary type="html">&lt;p&gt;Юрий Комаров: /* Статья Участник:Светлана Лукьяненко/Строгий алгоритм С средних (Hard C-Means, HCM) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Статья [[Участник:Светлана Лукьяненко/Строгий алгоритм С средних (Hard C-Means, HCM)]] =&lt;br /&gt;
&lt;br /&gt;
* Там действительно надо O(N*C) итераций или это какая-то оценка сверху? Откуда она взялась, кроме соображений того, что при превышении алгоритм бы был неэффективен? [[Участник:Chalker|Chalker]] ([[Обсуждение участника:Chalker|обсуждение]]) 23:22, 18 декабря 2016 (MSK)&lt;br /&gt;
** Исключительно из этих соображений, поскольку скорость сходимости алгоритма не определена. Более того, где-то в тексте было упомянуто, что к действительному минимуму он может не сходиться. [[Участник:Юрий Комаров|Комаров Юрий]]&lt;br /&gt;
* Ни ширина, ни высота не зависят от размерности векторов? [[Участник:Chalker|Chalker]] ([[Обсуждение участника:Chalker|обсуждение]]) 23:15, 18 декабря 2016 (MSK)&lt;br /&gt;
** Учтено. [[Участник:Юрий Комаров|Комаров Юрий]]&lt;br /&gt;
* «получаем итоговую сложность последовательной реализации алгоритма O(nNc) {\displaystyle O(nNc)} (в предположении, что n {\displaystyle n} и C {\displaystyle C} существенно меньше N {\displaystyle N})» — что имелось ввиду? [[Участник:Chalker|Chalker]] ([[Обсуждение участника:Chalker|обсуждение]]) 23:15, 18 декабря 2016 (MSK)&lt;br /&gt;
* 1.6 — «Ожидая, что предельная точность будет достигнута менее, чем за N итераций…» — у вас получается сложность алгоритма тогда не O(N), а O(N*сложность итерации), если итераций N штук. В литературе есть какие-то оценки требуемого количества итераций исходя из входных параметров? [[Участник:Chalker|Chalker]] ([[Обсуждение участника:Chalker|обсуждение]]) 18:21, 18 декабря 2016 (MSK)&lt;br /&gt;
** нет, оценок нет, поэтому предлагается оценить через O(NC) [[Участник:Юрий Комаров|Комаров Юрий]]&lt;br /&gt;
* 1.8 — высота не равна O(1) на вашем графе, она зависит в том числе от N. [[Участник:Chalker|Chalker]] ([[Обсуждение участника:Chalker|обсуждение]]) 23:48, 17 декабря 2016 (MSK)&lt;br /&gt;
* 1.6 — сложность не равна O(N), у вас одних только операций умножения строчкой выше O(nNC). [[Участник:Chalker|Chalker]] ([[Обсуждение участника:Chalker|обсуждение]]) 23:48, 17 декабря 2016 (MSK)&lt;br /&gt;
** Согласен, O(nNC). [[Участник:Юрий Комаров|Комаров Юрий]]&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Не указан вклад каждого автора [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:57, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:05, 31 октября 2016 (MSK)&lt;br /&gt;
* Значительная часть п. 1.2  совпадает с тем же пунктом из [[Участник:Каледа Александр/Строгий алгоритм С средних (Hard C-Means)]] [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:05, 25 октября 2016 (MSK)&lt;br /&gt;
** Замечание снимается [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:05, 31 октября 2016 (MSK)&lt;br /&gt;
* В списке литературы отсутствуют выходные данные публикаций, кроме названия и автора. По приведенным данным определить конкретную публикацию не представляется возможным. Стоит добавить ссылку на оригинальную публикацию с описанием алгоритма, упомянутую в начале п.1.1 [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:57, 25 октября 2016 (MSK)&lt;br /&gt;
** Не исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:05, 31 октября 2016 (MSK)&lt;br /&gt;
* Список литературы совпадает со списком из [[Участник:Каледа Александр/Строгий алгоритм С средних (Hard C-Means)]] [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:01, 25 октября 2016 (MSK)&lt;br /&gt;
** Замечание снимается [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:05, 31 октября 2016 (MSK)&lt;br /&gt;
----------------------&lt;br /&gt;
* Комментарий от [[Участник:Юрий Комаров|Комарова Юрия]]: Сравните, пожалуйста, нашу историю работы над статьёй с историей работы над статьёй наших коллег: Каледы и его товарища. Сделав это, Вы обнаружите, что мы начали работать сразу же после выдачи задания, практически одними из первых и гораздо раньше указанных ребят, и неоднократно правили каждый из пунктов, доводя их до лучшей кондиции. За то, что пункт 1.2, как, впрочем, и другие пункты, и список литературы были составлены нами лично в процессе длительной совместной работы со [[Участник:Светлана Лукьяненко|Светланой]], отвечаю головой. Надеюсь, вопрос о плагиате больше не возникнет. В такой ситуации исправлять что-то должны явно не мы. С уважением, Комаров Юрий.&lt;br /&gt;
** В мои задачи не входить обвинять кого-то в плагиате, проводить расследования, кто у кого списал, или выяснять, кто прав, а кто нет. Меня попросили проверить статью, обращая внимание на пересечения с другими на ту же тему. В двух статьях есть общая часть, это пошло в замечания к обеим статьям. Пересечение уйдет - замечание снимется. Кто исправит текст - мне все равно. Когда в статье появится метка, что ее можно снова проверять - я сравню тексты снова. Пока текст совпадает - замечание с моей стороны остается. Есть А.С. Антонов, если он сочтет, что это замечание можно проигнорировать (в одной статье или в обеих) - он продвинет статью дальше. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 18:31, 28 октября 2016 (MSK)&lt;br /&gt;
** Если говорить о, скажем мягко, некорректном заимствовании, то ваш п 1.2 есть воспроизведение фрагмента из работы Нейского с небольшими добавлениями. У вас имеется разрешение автора на такое воспроизведение? Так что не стоит так сразу головой-то... [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 18:31, 28 октября 2016 (MSK)&lt;br /&gt;
** В общем, не стоит отвечать в таком тоне. Я могу понять возмущение, но писать надо корректнее. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 18:31, 28 октября 2016 (MSK)&lt;br /&gt;
* Вклад авторов указан, в источниках приведены ссылки. Исправлять часть статьи, которую у нас украли наши коллеги (дата создания их страницы 15 октября), должны не мы, а указанные личности. К сожалению, заставить их это сделать мы не можем, полагаю, регулирование этого вопроса нам разумнее доверить проверяющим.&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
* В списке литературы отсутствуют выходные данные публикаций, кроме названия и автора. По приведенным данным определить конкретную публикацию не представляется возможным. Стоит добавить ссылку на оригинальную публикацию с описанием алгоритма, упомянутую в начале п.1.1  [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:05, 31 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:06, 3 ноября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
* п. 2.4. Не приведена ссылка на текст анализируемой программы. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:38, 17 ноября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:28, 22 ноября 2016 (MSK)&lt;br /&gt;
* Необходимо указать характеристики программно-аппаратной платформы (какой компилятор, с какими опциями использовался, какие версии библиотек, на каких узлах проводился запуск и т.д.) [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:28, 22 ноября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:14, 23 ноября 2016 (MSK)&lt;br /&gt;
* В подписи к рис. 3 указано, что это &#039;&#039;График производительности ... от числа параллельных процессов&#039;&#039;, а подписи к оси указано, что по ней отложено число процессоров (Processors). Какой вариант правильный? [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:28, 22 ноября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:14, 23 ноября 2016 (MSK)&lt;/div&gt;</summary>
		<author><name>Юрий Комаров</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=21265</id>
		<title>Участник:Светлана Лукьяненко/Строгий алгоритм С средних (Hard C-Means, HCM)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=21265"/>
		<updated>2016-12-18T20:29:31Z</updated>

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

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

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

		<summary type="html">&lt;p&gt;Юрий Комаров: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Статья [[Участник:Светлана Лукьяненко/Строгий алгоритм С средних (Hard C-Means, HCM)]] =&lt;br /&gt;
&lt;br /&gt;
* 1.6 — «Ожидая, что предельная точность будет достигнута менее, чем за N итераций…» — у вас получается сложность алгоритма тогда не O(N), а O(N*сложность итерации), если итераций N штук. В литературе есть какие-то оценки требуемого количества итераций исходя из входных параметров? [[Участник:Chalker|Chalker]] ([[Обсуждение участника:Chalker|обсуждение]]) 18:21, 18 декабря 2016 (MSK)&lt;br /&gt;
** нет, оценок нет, поэтому предлагается оценить через O(NC) [[Участник:Юрий Комаров|Комаров Юрий]]&lt;br /&gt;
* 1.8 — высота не равна O(1) на вашем графе, она зависит в том числе от N. [[Участник:Chalker|Chalker]] ([[Обсуждение участника:Chalker|обсуждение]]) 23:48, 17 декабря 2016 (MSK)&lt;br /&gt;
* 1.6 — сложность не равна O(N), у вас одних только операций умножения строчкой выше O(nNC). [[Участник:Chalker|Chalker]] ([[Обсуждение участника:Chalker|обсуждение]]) 23:48, 17 декабря 2016 (MSK)&lt;br /&gt;
** Согласен, O(nNC). [[Участник:Юрий Комаров|Комаров Юрий]]&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Не указан вклад каждого автора [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:57, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:05, 31 октября 2016 (MSK)&lt;br /&gt;
* Значительная часть п. 1.2  совпадает с тем же пунктом из [[Участник:Каледа Александр/Строгий алгоритм С средних (Hard C-Means)]] [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:05, 25 октября 2016 (MSK)&lt;br /&gt;
** Замечание снимается [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:05, 31 октября 2016 (MSK)&lt;br /&gt;
* В списке литературы отсутствуют выходные данные публикаций, кроме названия и автора. По приведенным данным определить конкретную публикацию не представляется возможным. Стоит добавить ссылку на оригинальную публикацию с описанием алгоритма, упомянутую в начале п.1.1 [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:57, 25 октября 2016 (MSK)&lt;br /&gt;
** Не исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:05, 31 октября 2016 (MSK)&lt;br /&gt;
* Список литературы совпадает со списком из [[Участник:Каледа Александр/Строгий алгоритм С средних (Hard C-Means)]] [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:01, 25 октября 2016 (MSK)&lt;br /&gt;
** Замечание снимается [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:05, 31 октября 2016 (MSK)&lt;br /&gt;
----------------------&lt;br /&gt;
* Комментарий от [[Участник:Юрий Комаров|Комарова Юрия]]: Сравните, пожалуйста, нашу историю работы над статьёй с историей работы над статьёй наших коллег: Каледы и его товарища. Сделав это, Вы обнаружите, что мы начали работать сразу же после выдачи задания, практически одними из первых и гораздо раньше указанных ребят, и неоднократно правили каждый из пунктов, доводя их до лучшей кондиции. За то, что пункт 1.2, как, впрочем, и другие пункты, и список литературы были составлены нами лично в процессе длительной совместной работы со [[Участник:Светлана Лукьяненко|Светланой]], отвечаю головой. Надеюсь, вопрос о плагиате больше не возникнет. В такой ситуации исправлять что-то должны явно не мы. С уважением, Комаров Юрий.&lt;br /&gt;
** В мои задачи не входить обвинять кого-то в плагиате, проводить расследования, кто у кого списал, или выяснять, кто прав, а кто нет. Меня попросили проверить статью, обращая внимание на пересечения с другими на ту же тему. В двух статьях есть общая часть, это пошло в замечания к обеим статьям. Пересечение уйдет - замечание снимется. Кто исправит текст - мне все равно. Когда в статье появится метка, что ее можно снова проверять - я сравню тексты снова. Пока текст совпадает - замечание с моей стороны остается. Есть А.С. Антонов, если он сочтет, что это замечание можно проигнорировать (в одной статье или в обеих) - он продвинет статью дальше. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 18:31, 28 октября 2016 (MSK)&lt;br /&gt;
** Если говорить о, скажем мягко, некорректном заимствовании, то ваш п 1.2 есть воспроизведение фрагмента из работы Нейского с небольшими добавлениями. У вас имеется разрешение автора на такое воспроизведение? Так что не стоит так сразу головой-то... [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 18:31, 28 октября 2016 (MSK)&lt;br /&gt;
** В общем, не стоит отвечать в таком тоне. Я могу понять возмущение, но писать надо корректнее. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 18:31, 28 октября 2016 (MSK)&lt;br /&gt;
* Вклад авторов указан, в источниках приведены ссылки. Исправлять часть статьи, которую у нас украли наши коллеги (дата создания их страницы 15 октября), должны не мы, а указанные личности. К сожалению, заставить их это сделать мы не можем, полагаю, регулирование этого вопроса нам разумнее доверить проверяющим.&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
* В списке литературы отсутствуют выходные данные публикаций, кроме названия и автора. По приведенным данным определить конкретную публикацию не представляется возможным. Стоит добавить ссылку на оригинальную публикацию с описанием алгоритма, упомянутую в начале п.1.1  [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:05, 31 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:06, 3 ноября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
* п. 2.4. Не приведена ссылка на текст анализируемой программы. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:38, 17 ноября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:28, 22 ноября 2016 (MSK)&lt;br /&gt;
* Необходимо указать характеристики программно-аппаратной платформы (какой компилятор, с какими опциями использовался, какие версии библиотек, на каких узлах проводился запуск и т.д.) [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:28, 22 ноября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:14, 23 ноября 2016 (MSK)&lt;br /&gt;
* В подписи к рис. 3 указано, что это &#039;&#039;График производительности ... от числа параллельных процессов&#039;&#039;, а подписи к оси указано, что по ней отложено число процессоров (Processors). Какой вариант правильный? [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:28, 22 ноября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:14, 23 ноября 2016 (MSK)&lt;/div&gt;</summary>
		<author><name>Юрий Комаров</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE&amp;diff=21210</id>
		<title>Обсуждение участника:Светлана Лукьяненко</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE&amp;diff=21210"/>
		<updated>2016-12-18T15:58:06Z</updated>

		<summary type="html">&lt;p&gt;Юрий Комаров: /* Статья Участник:Светлана Лукьяненко/Строгий алгоритм С средних (Hard C-Means, HCM) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Статья [[Участник:Светлана Лукьяненко/Строгий алгоритм С средних (Hard C-Means, HCM)]] =&lt;br /&gt;
&lt;br /&gt;
* 1.6 — «Ожидая, что предельная точность будет достигнута менее, чем за N итераций…» — у вас получается сложность алгоритма тогда не O(N), а O(N*сложность итерации), если итераций N штук. В литературе есть какие-то оценки требуемого количества итераций исходя из входных параметров? [[Участник:Chalker|Chalker]] ([[Обсуждение участника:Chalker|обсуждение]]) 18:21, 18 декабря 2016 (MSK)&lt;br /&gt;
** нет, оценок нет, поэтому предлагается оценить через O(NC) [[Участник:Юрий Комаров|Комаров Юрий]]&lt;br /&gt;
* 1.8 — высота не равна O(1) на вашем графе, она зависит в том числе от N. [[Участник:Chalker|Chalker]] ([[Обсуждение участника:Chalker|обсуждение]]) 23:48, 17 декабря 2016 (MSK)&lt;br /&gt;
* 1.6 — сложность не равна O(N), у вас одних только операций умножения строчкой выше O(nNC). [[Участник:Chalker|Chalker]] ([[Обсуждение участника:Chalker|обсуждение]]) 23:48, 17 декабря 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Не указан вклад каждого автора [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:57, 25 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:05, 31 октября 2016 (MSK)&lt;br /&gt;
* Значительная часть п. 1.2  совпадает с тем же пунктом из [[Участник:Каледа Александр/Строгий алгоритм С средних (Hard C-Means)]] [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:05, 25 октября 2016 (MSK)&lt;br /&gt;
** Замечание снимается [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:05, 31 октября 2016 (MSK)&lt;br /&gt;
* В списке литературы отсутствуют выходные данные публикаций, кроме названия и автора. По приведенным данным определить конкретную публикацию не представляется возможным. Стоит добавить ссылку на оригинальную публикацию с описанием алгоритма, упомянутую в начале п.1.1 [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:57, 25 октября 2016 (MSK)&lt;br /&gt;
** Не исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:05, 31 октября 2016 (MSK)&lt;br /&gt;
* Список литературы совпадает со списком из [[Участник:Каледа Александр/Строгий алгоритм С средних (Hard C-Means)]] [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:01, 25 октября 2016 (MSK)&lt;br /&gt;
** Замечание снимается [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:05, 31 октября 2016 (MSK)&lt;br /&gt;
----------------------&lt;br /&gt;
* Комментарий от [[Участник:Юрий Комаров|Комарова Юрия]]: Сравните, пожалуйста, нашу историю работы над статьёй с историей работы над статьёй наших коллег: Каледы и его товарища. Сделав это, Вы обнаружите, что мы начали работать сразу же после выдачи задания, практически одними из первых и гораздо раньше указанных ребят, и неоднократно правили каждый из пунктов, доводя их до лучшей кондиции. За то, что пункт 1.2, как, впрочем, и другие пункты, и список литературы были составлены нами лично в процессе длительной совместной работы со [[Участник:Светлана Лукьяненко|Светланой]], отвечаю головой. Надеюсь, вопрос о плагиате больше не возникнет. В такой ситуации исправлять что-то должны явно не мы. С уважением, Комаров Юрий.&lt;br /&gt;
** В мои задачи не входить обвинять кого-то в плагиате, проводить расследования, кто у кого списал, или выяснять, кто прав, а кто нет. Меня попросили проверить статью, обращая внимание на пересечения с другими на ту же тему. В двух статьях есть общая часть, это пошло в замечания к обеим статьям. Пересечение уйдет - замечание снимется. Кто исправит текст - мне все равно. Когда в статье появится метка, что ее можно снова проверять - я сравню тексты снова. Пока текст совпадает - замечание с моей стороны остается. Есть А.С. Антонов, если он сочтет, что это замечание можно проигнорировать (в одной статье или в обеих) - он продвинет статью дальше. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 18:31, 28 октября 2016 (MSK)&lt;br /&gt;
** Если говорить о, скажем мягко, некорректном заимствовании, то ваш п 1.2 есть воспроизведение фрагмента из работы Нейского с небольшими добавлениями. У вас имеется разрешение автора на такое воспроизведение? Так что не стоит так сразу головой-то... [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 18:31, 28 октября 2016 (MSK)&lt;br /&gt;
** В общем, не стоит отвечать в таком тоне. Я могу понять возмущение, но писать надо корректнее. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 18:31, 28 октября 2016 (MSK)&lt;br /&gt;
* Вклад авторов указан, в источниках приведены ссылки. Исправлять часть статьи, которую у нас украли наши коллеги (дата создания их страницы 15 октября), должны не мы, а указанные личности. К сожалению, заставить их это сделать мы не можем, полагаю, регулирование этого вопроса нам разумнее доверить проверяющим.&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
* В списке литературы отсутствуют выходные данные публикаций, кроме названия и автора. По приведенным данным определить конкретную публикацию не представляется возможным. Стоит добавить ссылку на оригинальную публикацию с описанием алгоритма, упомянутую в начале п.1.1  [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:05, 31 октября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:06, 3 ноября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
* п. 2.4. Не приведена ссылка на текст анализируемой программы. [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:38, 17 ноября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:28, 22 ноября 2016 (MSK)&lt;br /&gt;
* Необходимо указать характеристики программно-аппаратной платформы (какой компилятор, с какими опциями использовался, какие версии библиотек, на каких узлах проводился запуск и т.д.) [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:28, 22 ноября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:14, 23 ноября 2016 (MSK)&lt;br /&gt;
* В подписи к рис. 3 указано, что это &#039;&#039;График производительности ... от числа параллельных процессов&#039;&#039;, а подписи к оси указано, что по ней отложено число процессоров (Processors). Какой вариант правильный? [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 15:28, 22 ноября 2016 (MSK)&lt;br /&gt;
** Исправлено [[Участник:Coctic|К. Стефанов]] ([[Обсуждение участника:Coctic|обсуждение]]) 13:14, 23 ноября 2016 (MSK)&lt;/div&gt;</summary>
		<author><name>Юрий Комаров</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=21209</id>
		<title>Участник:Светлана Лукьяненко/Строгий алгоритм С средних (Hard C-Means, HCM)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=21209"/>
		<updated>2016-12-18T15:56:29Z</updated>

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

		<summary type="html">&lt;p&gt;Юрий Комаров: /* Свойства алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Строгий алгоритм С средних (Hard C-Means,HCM)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;nN+1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;C(N+n)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы описания: [[Участник:Светлана_Лукьяненко|Лукьяненко Светлана]], [[Участник:Юрий_Комаров|Комаров Юрий]].&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Строгий алгоритм C средних&#039;&#039;&#039; (&#039;&#039;&#039;&#039;&#039;Hard C-Means&#039;&#039;&#039;&#039;&#039;; &#039;&#039;Jang, Sun and Mizutani, 1997&#039;&#039;) позволяет распределить большие наборы числовых данных по кластерам в многомерном пространстве&amp;lt;ref&amp;gt;Jan Jantzen «Neurofuzzy Modelling». Электронное издание.&amp;lt;/ref&amp;gt;. Алгоритм является управляемым, так как для работы с ним требуется задание одного параметра — числа кластеров, на которое необходимо разделить данные. &lt;br /&gt;
Входными данными для алгоритма являются набор векторов и количество кластеров, также может задаваться пороговое значение величины объектной функции, по достижении которого расчёт прекращается. Выходными данными для алгоритма является рядовая матрица, отображающая принадлежность исходных элементов построенным кластерам, и центры построенных кластеров.&lt;br /&gt;
&lt;br /&gt;
Первым шагом выполнения алгоритма является инициализация центров кластеров случайными значениями. Дальнейшие шаги алгоритма выполняются итеративно до тех пор, пока объектная функция не станет меньше порогового значения или же значение объектной функции не будет минимально отличаться от полученного на предыдущей итерации. На каждой итерации вычислений выполняются следующие действия:&lt;br /&gt;
&lt;br /&gt;
# Расчёт рядовой матрицы, сопоставляющей каждый вектор с ближайшим кластерным центром.&lt;br /&gt;
# Расчёт объектной функции; проверка условий остановки и завершение расчёта в случае их выполнения.&lt;br /&gt;
# Пересчёт кластерных центров.&lt;br /&gt;
&lt;br /&gt;
Так как алгоритм является итеративным и зависит от начальных значений кластерных центров, он может сходиться к локальному минимуму.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
==== Входные и выходные данные ====&lt;br /&gt;
На вход подаётся набор векторов &amp;lt;math&amp;gt;\{u_k\}_{k=1}^{N}&amp;lt;/math&amp;gt; пространства &amp;lt;math&amp;gt;\mathbb{R}^n&amp;lt;/math&amp;gt; и количество кластеров &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Конечным результатом работы алгоритма являются построенная рядовая матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, содержащая информацию о принадлежности элементов кластерам:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ij} = \begin{cases}&lt;br /&gt;
1, &amp;amp; u_j \in C_i, \\&lt;br /&gt;
0, &amp;amp; \text{otherwise},&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; подразумевается &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый построенный кластер, и набор &amp;lt;math&amp;gt;\{c_i\}_{i=1}^{C}&amp;lt;/math&amp;gt; центров этих кластеров.&lt;br /&gt;
&lt;br /&gt;
==== Описание алгоритма ====&lt;br /&gt;
Алгоритм состоит из 5 последовательных шагов.&amp;lt;ref&amp;gt; Нейский И.М. Классификация и сравнение методов кластеризации.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 1&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация кластерных центров&#039;&#039;&#039; &amp;lt;math&amp;gt;c_i \, (i=1,2,\ldots,C)&amp;lt;/math&amp;gt; может происходить за счёт случайного выбора необходимого числа точек из входного набора либо путём явного указания.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 2&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вычисление рядовой матрицы&#039;&#039;&#039; &amp;lt;math&amp;gt;M = \|m_{ik}\|&amp;lt;/math&amp;gt;, элементы которой задаются следующими выражениями (&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; — количество элементов во входном наборе данных):&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ik} = \begin{cases}&lt;br /&gt;
1, &amp;amp; \|u_k-c_i\|^2 \leqslant \|u_k-c_j\|^2 \;\; \text{for all } i \neq j; \;\; (i,j=1,2,\ldots,C; \; k = 1,2,\ldots,N)\\&lt;br /&gt;
0, &amp;amp; \text{otherwise}.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;!-- При этом, как легко видеть, матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; обладает следующими свойствами:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\sum\limits_{i=1}^C m_{ij} = 1, \;\; \sum\limits_{i=1}^C\sum\limits_{j=1}^K m_{ij} = K.&lt;br /&gt;
&amp;lt;/math&amp;gt; --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Будем говорить, что &amp;lt;math&amp;gt;u_k \in C_i&amp;lt;/math&amp;gt;, если &amp;lt;math&amp;gt;m_{ik} = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 3&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Расчёт объектной функции:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^C J_i = \sum\limits_{i=1}^C \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right)&lt;br /&gt;
.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На этом шаге происходит &#039;&#039;&#039;&amp;lt;u&amp;gt;остановка и выход из цикла&amp;lt;/u&amp;gt;&#039;&#039;&#039;, если полученное значение ниже пороговой величины &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; или полученное значение не сильно отличается от значений, полученных на предыдущих циклах.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 4&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Пересчёт кластерных центров&#039;&#039;&#039; выполняется в соответствии со следующим уравнением:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;|C_i|&amp;lt;/math&amp;gt; подразумевается количество элементов в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом кластере.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 5&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Переход по циклу&#039;&#039;&#039; на шаг 2.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма составляют вычисления квадратов нормы расстояния от каждого из векторов исходной выборки до промежуточных кластерных центров &amp;lt;math&amp;gt;\|u_k-c_i\|^2&amp;lt;/math&amp;gt;. На каждой итерации алгоритма происходит расчёт &amp;lt;math&amp;gt;CN&amp;lt;/math&amp;gt; таких расстояний.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Основной операцией, выполняемой в алгоритме, как сказано выше, является операция нахождения квадратов расстояний между исходными векторами и кластерными центрами. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
d_{ki} = \|u_k-c_i\|^2&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также на шаге вычисления объектной функции производится множественное суммирование полученных расстояний:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^C J_i = \sum\limits_{i=1}^C \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right),&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
а на шаге расчета кластерных центров происходит суммирование векторов:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Реализация последовательного алгоритма состоит в итеративном повторении блока, описанного далее в форме псевдокода, до тех пор, пока не будет достигнута желаемая точность.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;&lt;br /&gt;
J = 0;&lt;br /&gt;
M = zeros(N,C);&lt;br /&gt;
for i = 1 to N //go through every element&lt;br /&gt;
   d_min = MAXINT;&lt;br /&gt;
   j_min = 1;&lt;br /&gt;
   for j = 1 to C //deside which claster does element belong to&lt;br /&gt;
      d_ij  = sq_norm(u[i] - c[j]);&lt;br /&gt;
      if d_ij &amp;lt; d_min&lt;br /&gt;
         d_min = d_ij;&lt;br /&gt;
         j_min = j;&lt;br /&gt;
   //generation of output data&lt;br /&gt;
   J += d_min; &lt;br /&gt;
   M[i,j_min] = 1;&lt;br /&gt;
   c_new[j] += u[i];&lt;br /&gt;
   c_newCount[k]++;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
На каждой итерации алгоритма требуется выполнение:&lt;br /&gt;
* &amp;lt;math&amp;gt;NC&amp;lt;/math&amp;gt; операций вычисления квадрата нормы разности элементов;&lt;br /&gt;
* &amp;lt;math&amp;gt;NC&amp;lt;/math&amp;gt; операций сравнения (вычитаний);&lt;br /&gt;
* &amp;lt;math&amp;gt;3N&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
&lt;br /&gt;
Каждая операция вычисления нормы разности векторов предполагает выполнение &amp;lt;math&amp;gt;2n-1&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания и &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; операций возведения в квадрат (умножений), поэтому получаем для каждой итерации:&lt;br /&gt;
* &amp;lt;math&amp;gt;(2nC + 3)N&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания;&lt;br /&gt;
* &amp;lt;math&amp;gt;nNC&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
&lt;br /&gt;
Ожидая, что предельная точность будет достигнута менее, чем за &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; итераций (в противном случае применение алгоритма можно считать нецелесообразным), получаем итоговую сложность последовательной реализации алгоритма &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt; (в предположении, что &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; существенно меньше &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Приведём аналитическое и графическое описание графа алгоритма.&lt;br /&gt;
&lt;br /&gt;
Граф алгоритма состоит из 5 различных видов вершин.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первая&#039;&#039;&#039; группа вершин отмечена символом &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039;, ей соответствует вычисление минимального расстояния до кластерных центров, включающее в себя следующую последовательность действий:&lt;br /&gt;
* независимое вычисление расстояний от заданного элемента &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; до каждого из кластерных центров;&lt;br /&gt;
* последовательное сравнение полученных значений с целью отыскания минимума;&lt;br /&gt;
* передача найденного минимального расстояния и соответствующего ему индекса кластера.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вторая&#039;&#039;&#039; группа вершин отмечена символом &#039;&#039;&#039;&#039;&#039;M&#039;&#039;&#039;&#039;&#039;, ей соответствует операция записи единички в столбец, отвечающий текущей ветке графа, в позицию, полученную на предыдущем шаге и соответствующую ближайшему кластерному центру.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Третья&#039;&#039;&#039; вершина отмечена символом &#039;&#039;&#039;&#039;&#039;J&#039;&#039;&#039;&#039;&#039;, подразумевается, что на этом этапе происходит расчёт объектной функции.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Четвертая&#039;&#039;&#039; вершина обозначена треугольным маркером и помечена &#039;&#039;&#039;&#039;&#039;if&#039;&#039;&#039;&#039;&#039;, на этом этапе происходит проверка условия достижения необходимой точности (условия остановки итерационного процесса).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Пятая&#039;&#039;&#039; соответствует операции пересчёта кластерных центров, она отмечена как &#039;&#039;&#039;&#039;&#039;{c}&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Все эти виды вершин визуально выделены в одну большую группу, поскольку все вместе они составляют одну полную итерацию алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:HardCMeans1.png|thumb|800px|center|Рисунок 1. Информационный граф алгоритма. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (&amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; стартовых значений кластерных центров и 1 значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; на каждую вершину графа), &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039; — вычисление минимального расстояния до кластерных центров (подробнее см. рисунок 2), &#039;&#039;&#039;&#039;&#039;M&#039;&#039;&#039;&#039;&#039; — запись единички в соответствующий столбец матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, &#039;&#039;&#039;&#039;&#039;J&#039;&#039;&#039;&#039;&#039; — вычисление объектной функции по результатам полученных вычислений, &#039;&#039;&#039;&#039;&#039;if&#039;&#039;&#039;&#039;&#039; — проверка условия достижения заданной точности, &#039;&#039;&#039;&#039;&#039;{c}&#039;&#039;&#039;&#039;&#039; — пересчёт кластерных центров и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; значений полученных кластерных центров).]]&lt;br /&gt;
[[File:HardCMeans2.PNG|thumb|400px|center|Рисунок 2. Подробное описание работы блока  &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039;. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (по 1 значению центра кластера на каждую из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; соответствующих вершин графа и значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;, единое для этого &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039;-блока), &#039;&#039;&#039;&#039;&#039;d1,...,dC&#039;&#039;&#039;&#039;&#039; — прямое вычисление  расстояния до кластерных центров, &#039;&#039;&#039;&#039;&#039;min&#039;&#039;&#039;&#039;&#039; — вычисление минимума двух чисел (с сохранением соответствующего минимуму кластерного индекса) и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (индекс кластерного центра, расположенного ближе всего к точке &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;, и соответствующее расстояние).]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
Для выполнения одной итерации алгоритма C средних необходимо выполнить параллельно ряд вычислений для каждого из &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; элементов:&lt;br /&gt;
&lt;br /&gt;
# Вычисление &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; расстояний между элементом и кластерными центрами.&lt;br /&gt;
# Выполнение &amp;lt;math&amp;gt;(C - 1)&amp;lt;/math&amp;gt; сравнений для определения минимального.&lt;br /&gt;
# Определение значений соответствующего рассматриваемому элементу &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; столбца матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Эта последовательность операций может быть выполнена для каждого элемента &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; входной выборки независимо и поэтому составляет основной ресурс параллелизма алгоритма.&lt;br /&gt;
&lt;br /&gt;
При этом, как можно видеть из информационного графа алгоритма, часть вычислений проводится в последовательном режиме, например, расчёт значения объектной функции &amp;lt;math&amp;gt;J&amp;lt;/math&amp;gt;. Аналогичная ситуация имеет место и с пересчётом кластерных центров — разделив эту операцию на &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; независимых процессов, мы потеряем в производительности за счёт увеличения накладных расходов, связанных с пересылкой данных и координацией вычислений.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что при малом объёме выборки и размерности системы попытка использования параллельной реализации алгоритма приведёт к понижению производительности, поскольку проведение последовательных расчётов потребует меньше времени, нежели пересылка данных (хотя бы матриц размера &amp;lt;math&amp;gt;nC&amp;lt;/math&amp;gt;, определяющих кластерные центры).&lt;br /&gt;
&lt;br /&gt;
При этом, как легко видеть, ширина [[глоссарий#Ярусно-параллельная форма графа алгоритма|ЯПФ]] составляет &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt; (если быть точнее, просто &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;). Высота ЯПФ для строгого алгоритма C средних оценивается как &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt; (предполагаем, что число итераций существенно меньше объёма выборки &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; &lt;br /&gt;
*&amp;lt;math&amp;gt;\{u_k\}_{k=1}^{N} \subset \mathbb{R}^n&amp;lt;/math&amp;gt; — исходный набор векторов;&lt;br /&gt;
*&amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; — количество кластеров (&amp;lt;math&amp;gt;2 \leqslant C \leqslant N&amp;lt;/math&amp;gt;);&lt;br /&gt;
* &#039;&#039;(опционально)&#039;&#039; &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; — пороговая точность работы алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;nN+1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
*&amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; — рядовая матрица из пространства &amp;lt;math&amp;gt;\mathbb{R}^{C \times N}&amp;lt;/math&amp;gt;.&lt;br /&gt;
*&amp;lt;math&amp;gt;\{c_k\}_{k=1}^{C}&amp;lt;/math&amp;gt; — набор построенных кластерных центров.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;C(N+n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Назначение:&#039;&#039;&#039; кластеризация больших наборов числовых данных.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Достоинства:&#039;&#039;&#039;&lt;br /&gt;
* лёгкость реализации;&lt;br /&gt;
* вычислительная простота.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Недостатки:&#039;&#039;&#039;&lt;br /&gt;
* нет гарантии, что итерационный процесс сойдётся к оптимальному решению;&lt;br /&gt;
* производительность существенно зависит от выбора начальных кластерных центров.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
1)  [https://github.com/artpar/Hard-Clustering-implementation Последовательная реализация на С++ ]&lt;br /&gt;
&lt;br /&gt;
2) [http://projects.jasmeet.me/2013/03/HardCMeans.html Последовательная реализация на MatLab ]&lt;br /&gt;
&lt;br /&gt;
На момент публикации параллельных реализаций в свободном доступе обнаружено не было.&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Юрий Комаров</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE&amp;diff=13751</id>
		<title>Обсуждение участника:Светлана Лукьяненко</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE&amp;diff=13751"/>
		<updated>2016-10-25T15:32:29Z</updated>

		<summary type="html">&lt;p&gt;Юрий Комаров: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Статья [[Строгий алгоритм С средних (Hard C-Means, HCM)]] =&lt;br /&gt;
* Не указан вклад каждого автора [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:57, 25 октября 2016 (MSK)&lt;br /&gt;
* Значительная часть п. 1.2  совпадает с тем же пунктом из [[Участник:Каледа Александр/Строгий алгоритм С средних (Hard C-Means)]] [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:05, 25 октября 2016 (MSK)&lt;br /&gt;
* В списке литературы отсутствуют выходные данные публикаций, кроме названия и автора. По приведенным данным определить конкретную публикацию не представляется возможным. Стоит добавить ссылку на оригинальную публикацию с описанием алгоритма, упомянутую в начале п.1.1 [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 10:57, 25 октября 2016 (MSK)&lt;br /&gt;
* Список литературы совпадает со списком из [[Участник:Каледа Александр/Строгий алгоритм С средних (Hard C-Means)]] [[Участник:Coctic|Coctic]] ([[Обсуждение участника:Coctic|обсуждение]]) 11:01, 25 октября 2016 (MSK)&lt;br /&gt;
----------------------&lt;br /&gt;
* Комментарий от [[Участник:Юрий Комаров|Комарова Юрия]]: Сравните, пожалуйста, нашу историю работы над статьёй с историей работы над статьёй наших коллег: Каледы и его товарища. Сделав это, Вы обнаружите, что мы начали работать сразу же после выдачи задания, практически одними из первых и гораздо раньше указанных ребят, и неоднократно правили каждый из пунктов, доводя их до лучшей кондиции. За то, что пункт 1.2, как, впрочем, и другие пункты, и список литературы были составлены нами лично в процессе длительной совместной работы со [[Участник:Светлана Лукьяненко|Светланой]], отвечаю головой. Надеюсь, вопрос о плагиате больше не возникнет. В такой ситуации исправлять что-то должны явно не мы. С уважением, Комаров Юрий.&lt;/div&gt;</summary>
		<author><name>Юрий Комаров</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=11583</id>
		<title>Участник:Светлана Лукьяненко/Строгий алгоритм С средних (Hard C-Means, HCM)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=11583"/>
		<updated>2016-10-15T19:55:27Z</updated>

		<summary type="html">&lt;p&gt;Юрий Комаров: /* Информационный граф */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Строгий алгоритм С средних (Hard C-Means,HCM)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;nN+1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;C(N+n)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы описания: [[Участник:Светлана_Лукьяненко|Лукьяненко Светлана]], [[Участник:Юрий_Комаров|Комаров Юрий]].&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Строгий алгоритм C средних&#039;&#039;&#039; (&#039;&#039;&#039;&#039;&#039;Hard C-Means&#039;&#039;&#039;&#039;&#039;; &#039;&#039;Jang, Sun and Mizutani, 1997&#039;&#039;) позволяет распределить большие наборы числовых данных по кластерам в многомерном пространстве&amp;lt;ref&amp;gt;Jan Jantzen «Neurofuzzy Modelling». Электронное издание.&amp;lt;/ref&amp;gt;. Алгоритм является управляемым, так как для работы с ним требуется задание одного параметра — числа кластеров, на которое необходимо разделить данные. &lt;br /&gt;
Входными данными для алгоритма являются набор векторов и количество кластеров, также может задаваться пороговое значение величины объектной функции, по достижении которого расчёт прекращается. Выходными данными для алгоритма является рядовая матрица, отображающая принадлежность исходных элементов построенным кластерам, и центры построенных кластеров.&lt;br /&gt;
&lt;br /&gt;
Первым шагом выполнения алгоритма является инициализация центров кластеров случайными значениями. Дальнейшие шаги алгоритма выполняются итеративно до тех пор, пока объектная функция не станет меньше порогового значения или же значение объектной функции не будет минимально отличаться от полученного на предыдущей итерации. На каждой итерации вычислений выполняются следующие действия:&lt;br /&gt;
&lt;br /&gt;
# Расчёт рядовой матрицы, сопоставляющей каждый вектор с ближайшим кластерным центром.&lt;br /&gt;
# Расчёт объектной функции; проверка условий остановки и завершение расчёта в случае их выполнения.&lt;br /&gt;
# Пересчёт кластерных центров.&lt;br /&gt;
&lt;br /&gt;
Так как алгоритм является итеративным и зависит от начальных значений кластерных центров, он может сходиться к локальному минимуму.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
==== Входные и выходные данные ====&lt;br /&gt;
На вход подаётся набор векторов &amp;lt;math&amp;gt;\{u_k\}_{k=1}^{N}&amp;lt;/math&amp;gt; пространства &amp;lt;math&amp;gt;\mathbb{R}^n&amp;lt;/math&amp;gt; и количество кластеров &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Конечным результатом работы алгоритма являются построенная рядовая матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, содержащая информацию о принадлежности элементов кластерам:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ij} = \begin{cases}&lt;br /&gt;
1, &amp;amp; u_j \in C_i, \\&lt;br /&gt;
0, &amp;amp; \text{otherwise},&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; подразумевается &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый построенный кластер, и набор &amp;lt;math&amp;gt;\{c_i\}_{i=1}^{C}&amp;lt;/math&amp;gt; центров этих кластеров.&lt;br /&gt;
&lt;br /&gt;
==== Описание алгоритма ====&lt;br /&gt;
Алгоритм состоит из 5 последовательных шагов.&amp;lt;ref&amp;gt; Нейский И.М. Классификация и сравнение методов кластеризации.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 1&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация кластерных центров&#039;&#039;&#039; &amp;lt;math&amp;gt;c_i \, (i=1,2,\ldots,C)&amp;lt;/math&amp;gt; может происходить за счёт случайного выбора необходимого числа точек из входного набора либо путём явного указания.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 2&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вычисление рядовой матрицы&#039;&#039;&#039; &amp;lt;math&amp;gt;M = \|m_{ik}\|&amp;lt;/math&amp;gt;, элементы которой задаются следующими выражениями (&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; — количество элементов во входном наборе данных):&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ik} = \begin{cases}&lt;br /&gt;
1, &amp;amp; \|u_k-c_i\|^2 \leqslant \|u_k-c_j\|^2 \;\; \text{for all } i \neq j; \;\; (i,j=1,2,\ldots,C; \; k = 1,2,\ldots,N)\\&lt;br /&gt;
0, &amp;amp; \text{otherwise}.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;!-- При этом, как легко видеть, матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; обладает следующими свойствами:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\sum\limits_{i=1}^C m_{ij} = 1, \;\; \sum\limits_{i=1}^C\sum\limits_{j=1}^K m_{ij} = K.&lt;br /&gt;
&amp;lt;/math&amp;gt; --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Будем говорить, что &amp;lt;math&amp;gt;u_k \in C_i&amp;lt;/math&amp;gt;, если &amp;lt;math&amp;gt;m_{ik} = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 3&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Расчёт объектной функции:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^C J_i = \sum\limits_{i=1}^C \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right)&lt;br /&gt;
.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На этом шаге происходит &#039;&#039;&#039;&amp;lt;u&amp;gt;остановка и выход из цикла&amp;lt;/u&amp;gt;&#039;&#039;&#039;, если полученное значение ниже пороговой величины &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; или полученное значение не сильно отличается от значений, полученных на предыдущих циклах.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 4&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Пересчёт кластерных центров&#039;&#039;&#039; выполняется в соответствии со следующим уравнением:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;|C_i|&amp;lt;/math&amp;gt; подразумевается количество элементов в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом кластере.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 5&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Переход по циклу&#039;&#039;&#039; на шаг 2.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма составляют вычисления квадратов нормы расстояния от каждого из векторов исходной выборки до промежуточных кластерных центров &amp;lt;math&amp;gt;\|u_k-c_i\|^2&amp;lt;/math&amp;gt;. На каждой итерации алгоритма происходит расчёт &amp;lt;math&amp;gt;CN&amp;lt;/math&amp;gt; таких расстояний.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Основной операцией, выполняемой в алгоритме, как сказано выше, является операция нахождения квадратов расстояний между исходными векторами и кластерными центрами. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
d_{ki} = \|u_k-c_i\|^2&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также на шаге вычисления объектной функции производится множественное суммирование полученных расстояний:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^C J_i = \sum\limits_{i=1}^C \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right),&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
а на шаге расчета кластерных центров происходит суммирование векторов:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Реализация последовательного алгоритма состоит в итеративном повторении блока, описанного далее в форме псевдокода, до тех пор, пока не будет достигнута желаемая точность.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;&lt;br /&gt;
J = 0;&lt;br /&gt;
M = zeros(N,C);&lt;br /&gt;
for i = 1 to N //go through every element&lt;br /&gt;
   d_min = MAXINT;&lt;br /&gt;
   j_min = 1;&lt;br /&gt;
   for j = 1 to C //deside which claster does element belong to&lt;br /&gt;
      d_ij  = sq_norm(u[i] - c[j]);&lt;br /&gt;
      if d_ij &amp;lt; d_min&lt;br /&gt;
         d_min = d_ij;&lt;br /&gt;
         j_min = j;&lt;br /&gt;
   //generation of output data&lt;br /&gt;
   J += d_min; &lt;br /&gt;
   M[i,j_min] = 1;&lt;br /&gt;
   c_new[j] += u[i];&lt;br /&gt;
   c_newCount[k]++;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
На каждой итерации алгоритма требуется выполнение:&lt;br /&gt;
* &amp;lt;math&amp;gt;NC&amp;lt;/math&amp;gt; операций вычисления квадрата нормы разности элементов;&lt;br /&gt;
* &amp;lt;math&amp;gt;NC&amp;lt;/math&amp;gt; операций сравнения (вычитаний);&lt;br /&gt;
* &amp;lt;math&amp;gt;3N&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
&lt;br /&gt;
Каждая операция вычисления нормы разности векторов предполагает выполнение &amp;lt;math&amp;gt;2n-1&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания и &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; операций возведения в квадрат (умножений), поэтому получаем для каждой итерации:&lt;br /&gt;
* &amp;lt;math&amp;gt;(2nC + 3)N&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания;&lt;br /&gt;
* &amp;lt;math&amp;gt;nNC&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
&lt;br /&gt;
Ожидая, что предельная точность будет достигнута менее, чем за &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; итераций (в противном случае применение алгоритма можно считать нецелесообразным), получаем итоговую сложность последовательной реализации алгоритма &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt; (в предположении, что &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; существенно меньше &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Приведём аналитическое и графическое описание графа алгоритма.&lt;br /&gt;
&lt;br /&gt;
Граф алгоритма состоит из 5 различных видов вершин.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первая&#039;&#039;&#039; группа вершин отмечена символом &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039;, ей соответствует вычисление минимального расстояния до кластерных центров, включающее в себя следующую последовательность действий:&lt;br /&gt;
* независимое вычисление расстояний от заданного элемента &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; до каждого из кластерных центров;&lt;br /&gt;
* последовательное сравнение полученных значений с целью отыскания минимума;&lt;br /&gt;
* передача найденного минимального расстояния и соответствующего ему индекса кластера.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вторая&#039;&#039;&#039; группа вершин отмечена символом &#039;&#039;&#039;&#039;&#039;M&#039;&#039;&#039;&#039;&#039;, ей соответствует операция записи единички в столбец, отвечающий текущей ветке графа, в позицию, полученную на предыдущем шаге и соответствующую ближайшему кластерному центру.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Третья&#039;&#039;&#039; вершина отмечена символом &#039;&#039;&#039;&#039;&#039;J&#039;&#039;&#039;&#039;&#039;, подразумевается, что на этом этапе происходит расчёт объектной функции.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Четвертая&#039;&#039;&#039; вершина обозначена треугольным маркером и помечена &#039;&#039;&#039;&#039;&#039;if&#039;&#039;&#039;&#039;&#039;, на этом этапе происходит проверка условия достижения необходимой точности (условия остановки итерационного процесса).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Пятая&#039;&#039;&#039; соответствует операции пересчёта кластерных центров, она отмечена как &#039;&#039;&#039;&#039;&#039;{c}&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Все эти виды вершин визуально выделены в одну большую группу, поскольку все вместе они составляют одну полную итерацию алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:HardCMeans1.png|thumb|800px|center|Рисунок 1. Информационный граф алгоритма. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (&amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; стартовых значений кластерных центров и 1 значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; на каждую вершину графа), &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039; — вычисление минимального расстояния до кластерных центров (подробнее см. рисунок 2), &#039;&#039;&#039;&#039;&#039;M&#039;&#039;&#039;&#039;&#039; — запись единички в соответствующий столбец матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, &#039;&#039;&#039;&#039;&#039;J&#039;&#039;&#039;&#039;&#039; — вычисление объектной функции по результатам полученных вычислений, &#039;&#039;&#039;&#039;&#039;if&#039;&#039;&#039;&#039;&#039; — проверка условия достижения заданной точности, &#039;&#039;&#039;&#039;&#039;{c}&#039;&#039;&#039;&#039;&#039; — пересчёт кластерных центров и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; значений полученных кластерных центров).]]&lt;br /&gt;
[[File:HardCMeans2.PNG|thumb|400px|center|Рисунок 2. Подробное описание работы блока  &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039;. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (по 1 значению центра кластера на каждую из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; соответствующих вершин графа и значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;, единое для этого &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039;-блока), &#039;&#039;&#039;&#039;&#039;d1,...,dC&#039;&#039;&#039;&#039;&#039; — прямое вычисление  расстояния до кластерных центров, &#039;&#039;&#039;&#039;&#039;min&#039;&#039;&#039;&#039;&#039; — вычисление минимума двух чисел (с сохранением соответствующего минимуму кластерного индекса) и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (индекс кластерного центра, расположенного ближе всего к точке &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;, и соответствующее расстояние).]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
Для выполнения одной итерации алгоритма C средних необходимо выполнить параллельно ряд вычислений для каждого из &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; элементов:&lt;br /&gt;
&lt;br /&gt;
# Вычисление &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; расстояний между элементом и кластерными центрами.&lt;br /&gt;
# Выполнение &amp;lt;math&amp;gt;(C - 1)&amp;lt;/math&amp;gt; сравнений для определения минимального.&lt;br /&gt;
# Определение значений соответствующего рассматриваемому элементу &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; столбца матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Эта последовательность операций может быть выполнена для каждого элемента &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; входной выборки независимо и поэтому составляет основной ресурс параллелизма алгоритма.&lt;br /&gt;
&lt;br /&gt;
При этом, как можно видеть из информационного графа алгоритма, часть вычислений проводится в последовательном режиме, например, расчёт значения объектной функции &amp;lt;math&amp;gt;J&amp;lt;/math&amp;gt;. Аналогичная ситуация имеет место и с пересчётом кластерных центров — разделив эту операцию на &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; независимых процессов, мы потеряем в производительности за счёт увеличения накладных расходов, связанных с пересылкой данных и координацией вычислений.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что при малом объёме выборки и размерности системы попытка использования параллельной реализации алгоритма приведёт к понижению производительности, поскольку проведение последовательных расчётов потребует меньше времени, нежели пересылка данных (хотя бы матриц размера &amp;lt;math&amp;gt;nC&amp;lt;/math&amp;gt;, определяющих кластерные центры).&lt;br /&gt;
&lt;br /&gt;
При этом, как легко видеть, ширина [[глоссарий#Ярусно-параллельная форма графа алгоритма|ЯПФ]] составляет &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt; (если быть точнее, просто &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;). Высота ЯПФ для строгого алгоритма C средних оценивается как &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt; (предполагаем, что число итераций существенно меньше объёма выборки &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; &lt;br /&gt;
*&amp;lt;math&amp;gt;\{u_k\}_{k=1}^{N} \subset \mathbb{R}^n&amp;lt;/math&amp;gt; — исходный набор векторов;&lt;br /&gt;
*&amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; — количество кластеров (&amp;lt;math&amp;gt;2 \leqslant C \leqslant N&amp;lt;/math&amp;gt;);&lt;br /&gt;
* &#039;&#039;(опционально)&#039;&#039; &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; — пороговая точность работы алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;nN+1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
*&amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; — рядовая матрица из пространства &amp;lt;math&amp;gt;\mathbb{R}^{C \times N}&amp;lt;/math&amp;gt;.&lt;br /&gt;
*&amp;lt;math&amp;gt;\{c_k\}_{k=1}^{C}&amp;lt;/math&amp;gt; — набор построенных кластерных центров.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;C(N+n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Назначение:&#039;&#039;&#039; кластеризация больших наборов числовых данных.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Достоинства:&#039;&#039;&#039;&lt;br /&gt;
* лёгкость реализации;&lt;br /&gt;
* вычислительная простота.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Недостатки:&#039;&#039;&#039;&lt;br /&gt;
* нет гарантии, что итеративный процесс сойдётся к оптимальному решению;&lt;br /&gt;
* производительность существенно зависит от выбора начальных кластерных центров.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
1)  [https://github.com/artpar/Hard-Clustering-implementation Последовательная реализация на С++ ]&lt;br /&gt;
&lt;br /&gt;
2) [http://projects.jasmeet.me/2013/03/HardCMeans.html Последовательная реализация на MatLab ]&lt;br /&gt;
&lt;br /&gt;
На момент публикации параллельных реализаций в свободном доступе обнаружено не было.&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Юрий Комаров</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=8713</id>
		<title>Участник:Светлана Лукьяненко/Строгий алгоритм С средних (Hard C-Means, HCM)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=8713"/>
		<updated>2016-10-15T07:25:43Z</updated>

		<summary type="html">&lt;p&gt;Юрий Комаров: /* Информационный граф */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Строгий алгоритм С средних (Hard C-Means,HCM)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;nN+1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;C(N+n)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы описания: [[Участник:Светлана_Лукьяненко|Лукьяненко Светлана]], [[Участник:Юрий_Комаров|Комаров Юрий]].&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Строгий алгоритм C средних&#039;&#039;&#039; (&#039;&#039;&#039;&#039;&#039;Hard C-Means&#039;&#039;&#039;&#039;&#039;; &#039;&#039;Jang, Sun and Mizutani, 1997&#039;&#039;) позволяет распределить большие наборы числовых данных по кластерам в многомерном пространстве&amp;lt;ref&amp;gt;Jan Jantzen «Neurofuzzy Modelling». Электронное издание.&amp;lt;/ref&amp;gt;. Алгоритм является управляемым, так как для работы с ним требуется задание одного параметра — числа кластеров, на которое необходимо разделить данные. &lt;br /&gt;
Входными данными для алгоритма являются набор векторов и количество кластеров, также может задаваться пороговое значение величины объектной функции, по достижении которого расчёт прекращается. Выходными данными для алгоритма является рядовая матрица, отображающая принадлежность исходных элементов построенным кластерам, и центры построенных кластеров.&lt;br /&gt;
&lt;br /&gt;
Первым шагом выполнения алгоритма является инициализация центров кластеров случайными значениями. Дальнейшие шаги алгоритма выполняются итеративно до тех пор, пока объектная функция не станет меньше порогового значения или же значение объектной функции не будет минимально отличаться от полученного на предыдущей итерации. На каждой итерации вычислений выполняются следующие действия:&lt;br /&gt;
&lt;br /&gt;
# Расчёт рядовой матрицы, сопоставляющей каждый вектор с ближайшим кластерным центром.&lt;br /&gt;
# Расчёт объектной функции; проверка условий остановки и завершение расчёта в случае их выполнения.&lt;br /&gt;
# Пересчёт кластерных центров.&lt;br /&gt;
&lt;br /&gt;
Так как алгоритм является итеративным и зависит от начальных значений кластерных центров, он может не сходиться к локальному минимуму.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
==== Входные и выходные данные ====&lt;br /&gt;
На вход подаётся набор векторов &amp;lt;math&amp;gt;\{u_k\}_{k=1}^{N}&amp;lt;/math&amp;gt; пространства &amp;lt;math&amp;gt;\mathbb{R}^n&amp;lt;/math&amp;gt; и количество кластеров &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Конечным результатом работы алгоритма являются построенная рядовая матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, содержащая информацию о принадлежности элементов кластерам:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ij} = \begin{cases}&lt;br /&gt;
1, &amp;amp; u_j \in C_i, \\&lt;br /&gt;
0, &amp;amp; \text{otherwise},&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; подразумевается &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый построенный кластер, и набор &amp;lt;math&amp;gt;\{c_i\}_{i=1}^{C}&amp;lt;/math&amp;gt; центров этих кластеров.&lt;br /&gt;
&lt;br /&gt;
==== Описание алгоритма ====&lt;br /&gt;
Алгоритм состоит из 5 последовательных шагов.&amp;lt;ref&amp;gt; Нейский И.М. Классификация и сравнение методов кластеризации.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 1&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация кластерных центров&#039;&#039;&#039; &amp;lt;math&amp;gt;c_i \, (i=1,2,\ldots,C)&amp;lt;/math&amp;gt; может происходить за счёт случайного выбора необходимого числа точек из входного набора либо путём явного указания.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 2&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вычисление рядовой матрицы&#039;&#039;&#039; &amp;lt;math&amp;gt;M = \|m_{ik}\|&amp;lt;/math&amp;gt;, элементы которой задаются следующими выражениями (&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; — количество элементов во входном наборе данных):&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ik} = \begin{cases}&lt;br /&gt;
1, &amp;amp; \|u_k-c_i\|^2 \leqslant \|u_k-c_j\|^2 \;\; \text{for all } i \neq j; \;\; (i,j=1,2,\ldots,C; \; k = 1,2,\ldots,N)\\&lt;br /&gt;
0, &amp;amp; \text{otherwise}.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;!-- При этом, как легко видеть, матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; обладает следующими свойствами:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\sum\limits_{i=1}^C m_{ij} = 1, \;\; \sum\limits_{i=1}^C\sum\limits_{j=1}^K m_{ij} = K.&lt;br /&gt;
&amp;lt;/math&amp;gt; --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Будем говорить, что &amp;lt;math&amp;gt;u_k \in C_i&amp;lt;/math&amp;gt;, если &amp;lt;math&amp;gt;m_{ik} = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 3&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Расчёт объектной функции:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^C J_i = \sum\limits_{i=1}^C \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right)&lt;br /&gt;
.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На этом шаге происходит &#039;&#039;&#039;&amp;lt;u&amp;gt;остановка и выход из цикла&amp;lt;/u&amp;gt;&#039;&#039;&#039;, если полученное значение ниже пороговой величины &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; или полученное значение не сильно отличается от значений, полученных на предыдущих циклах.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 4&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Пересчёт кластерных центров&#039;&#039;&#039; выполняется в соответствии со следующим уравнением:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;|C_i|&amp;lt;/math&amp;gt; подразумевается количество элементов в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом кластере.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 5&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Переход по циклу&#039;&#039;&#039; на шаг 2.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма составляют вычисления квадратов нормы расстояния от каждого из векторов исходной выборки до промежуточных кластерных центров &amp;lt;math&amp;gt;\|u_k-c_i\|^2&amp;lt;/math&amp;gt;. На каждой итерации алгоритма происходит расчёт &amp;lt;math&amp;gt;CN&amp;lt;/math&amp;gt; таких расстояний.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Основной операцией, выполняемой в алгоритме, как сказано выше, является операция нахождения квадратов расстояний между исходными векторами и кластерными центрами. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
d_{ki} = \|u_k-c_i\|^2&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также на шаге вычисления объектной функции производится множественное суммирование полученных расстояний:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^C J_i = \sum\limits_{i=1}^C \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right),&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
а на шаге расчета кластерных центров происходит суммирование векторов:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Реализация последовательного алгоритма состоит в итеративном повторении блока, описанного далее в форме псевдокода, до тех пор, пока не будет достигнута желаемая точность.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;&lt;br /&gt;
J = 0;&lt;br /&gt;
M = zeros(N,C);&lt;br /&gt;
for i = 1 to N //go through every element&lt;br /&gt;
   d_min = MAXINT;&lt;br /&gt;
   j_min = 1;&lt;br /&gt;
   for j = 1 to C //deside which claster does element belong to&lt;br /&gt;
      d_ij  = sq_norm(u[i] - c[j]);&lt;br /&gt;
      if d_ij &amp;lt; d_min&lt;br /&gt;
         d_min = d_ij;&lt;br /&gt;
         j_min = j;&lt;br /&gt;
   //generation of output data&lt;br /&gt;
   J += d_min; &lt;br /&gt;
   M[i,j_min] = 1;&lt;br /&gt;
   c_new[j] += u[i];&lt;br /&gt;
   c_newCount[k]++;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
На каждой итерации алгоритма требуется выполнение:&lt;br /&gt;
* &amp;lt;math&amp;gt;NC&amp;lt;/math&amp;gt; операций вычисления квадрата нормы разности элементов;&lt;br /&gt;
* &amp;lt;math&amp;gt;NC&amp;lt;/math&amp;gt; операций сравнения (вычитаний);&lt;br /&gt;
* &amp;lt;math&amp;gt;3N&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
&lt;br /&gt;
Каждая операция вычисления нормы разности векторов предполагает выполнение &amp;lt;math&amp;gt;2n-1&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания и &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; операций возведения в квадрат (умножений), поэтому получаем для каждой итерации:&lt;br /&gt;
* &amp;lt;math&amp;gt;(2nC + 3)N&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания;&lt;br /&gt;
* &amp;lt;math&amp;gt;nNC&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
&lt;br /&gt;
Ожидая, что предельная точность будет достигнута менее, чем за &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; итераций (в противном случае применение алгоритма можно считать нецелесообразным), получаем итоговую сложность последовательной реализации алгоритма &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt; (в предположении, что &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; существенно меньше &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Приведём аналитическое и графическое описание графа алгоритма.&lt;br /&gt;
&lt;br /&gt;
Граф алгоритма состоит из 5 различных видов вершин.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первая&#039;&#039;&#039; группа вершин отмечена символом &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039;, ей соответствует вычисление минимального расстояния до кластерных центров, включающее в себя следующую последовательность действий:&lt;br /&gt;
* независимое вычисление расстояний от заданного элемента &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; до каждого из кластерных центров;&lt;br /&gt;
* последовательное сравнение полученных значений с целью отыскания максимума;&lt;br /&gt;
* передача найденного минимального расстояния и соответствующего ему индекса кластера.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вторая&#039;&#039;&#039; группа вершин отмечена символом &#039;&#039;&#039;&#039;&#039;M&#039;&#039;&#039;&#039;&#039;, ей соответствует операция записи 1 в столбец, отвечающий ветке графа, в позицию, полученную на предыдущем шаге и соответствующую ближайшему кластерному центру.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Третья&#039;&#039;&#039; вершина отмечена символом &#039;&#039;&#039;&#039;&#039;J&#039;&#039;&#039;&#039;&#039;, подразумевается, что на этом этапе происходит расчёт объектной функции.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Четвертая&#039;&#039;&#039; вершина обозначена треугольным маркером и помечена &#039;&#039;&#039;&#039;&#039;if&#039;&#039;&#039;&#039;&#039;, на этом этапе происходит проверка условия достижения необходимой точности (условия остановки итерационного процесса).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Пятая&#039;&#039;&#039; соответствует операции пересчёта кластерных центров, она отмечена как &#039;&#039;&#039;&#039;&#039;{c}&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Все эти виды вершин визуально выделены в одну большую группу, поскольку все вместе они составляют одну полную итерацию алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:HardCMeans1.png|thumb|800px|center|Рисунок 1. Информационный граф алгоритма. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (&amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; стартовых значений кластерных центров и 1 значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; на каждую вершину графа), &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039; — вычисление минимального расстояния до кластерных центров (подробнее см. рисунок 2), &#039;&#039;&#039;&#039;&#039;M&#039;&#039;&#039;&#039;&#039; — запись единички в соответствующий столбец матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, &#039;&#039;&#039;&#039;&#039;J&#039;&#039;&#039;&#039;&#039; — вычисление объектной функции по результатам полученных вычислений, &#039;&#039;&#039;&#039;&#039;if&#039;&#039;&#039;&#039;&#039; — проверка условия достижения заданной точности, &#039;&#039;&#039;&#039;&#039;{c}&#039;&#039;&#039;&#039;&#039; — пересчёт кластерных центров и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; значений полученных кластерных центров).]]&lt;br /&gt;
[[File:HardCMeans2.PNG|thumb|400px|center|Рисунок 2. Подробное описание работы блока  &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039;. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (по 1 значению центра кластера на каждую из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; соответствующих вершин графа и значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;, единое для этого &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039;-блока), &#039;&#039;&#039;&#039;&#039;d1,...,dC&#039;&#039;&#039;&#039;&#039; — прямое вычисление  расстояния до кластерных центров, &#039;&#039;&#039;&#039;&#039;max&#039;&#039;&#039;&#039;&#039; — вычисление максимума двух чисел (с сохранением соответствующего максимуму кластерного индекса) и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (индекс кластерного центра, расположенного ближе всего к точке &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;, и соответствующее расстояние).]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
Для выполнения одной итерации алгоритма C средних необходимо выполнить параллельно ряд вычислений для каждого из &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; элементов:&lt;br /&gt;
&lt;br /&gt;
# Вычисление &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; расстояний между элементом и кластерными центрами.&lt;br /&gt;
# Выполнение &amp;lt;math&amp;gt;(C - 1)&amp;lt;/math&amp;gt; сравнений для определения минимального.&lt;br /&gt;
# Определение значений соответствующего рассматриваемому элементу &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; столбца матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Эта последовательность операций может быть выполнена для каждого элемента &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; входной выборки независимо и поэтому составляет основной ресурс параллелизма алгоритма.&lt;br /&gt;
&lt;br /&gt;
При этом, как можно видеть из информационного графа алгоритма, часть вычислений проводится в последовательном режиме, например, расчёт значения объектной функции &amp;lt;math&amp;gt;J&amp;lt;/math&amp;gt;. Аналогичная ситуация имеет место и с пересчётом кластерных центров — разделив эту операцию на &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; независимых процессов, мы потеряем в производительности за счёт увеличения накладных расходов, связанных с пересылкой данных и координацией вычислений.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что при малом объёме выборки и размерности системы попытка использования параллельной реализации алгоритма приведёт к понижению производительности, поскольку проведение последовательных расчётов потребует меньше времени, нежели пересылка данных (хотя бы матриц размера &amp;lt;math&amp;gt;nC&amp;lt;/math&amp;gt;, определяющих кластерные центры).&lt;br /&gt;
&lt;br /&gt;
При этом, как легко видеть, ширина [[глоссарий#Ярусно-параллельная форма графа алгоритма|ЯПФ]] составляет &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt; (если быть точнее, просто &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;). Высота ЯПФ для строгого алгоритма C средних оценивается как &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt; (предполагаем, что число итераций существенно меньше объёма выборки &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; &lt;br /&gt;
*&amp;lt;math&amp;gt;\{u_k\}_{k=1}^{N} \subset \mathbb{R}^n&amp;lt;/math&amp;gt; — исходный набор векторов;&lt;br /&gt;
*&amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; — количество кластеров (&amp;lt;math&amp;gt;2 \leqslant C \leqslant N&amp;lt;/math&amp;gt;);&lt;br /&gt;
* &#039;&#039;(опционально)&#039;&#039; &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; — пороговая точность работы алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;nN+1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
*&amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; — рядовая матрица из пространства &amp;lt;math&amp;gt;\mathbb{R}^{C \times N}&amp;lt;/math&amp;gt;.&lt;br /&gt;
*&amp;lt;math&amp;gt;\{c_k\}_{k=1}^{C}&amp;lt;/math&amp;gt; — набор построенных кластерных центров.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;C(N+n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Назначение:&#039;&#039;&#039; кластеризация больших наборов числовых данных.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Достоинства:&#039;&#039;&#039;&lt;br /&gt;
* лёгкость реализации;&lt;br /&gt;
* вычислительная простота.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Недостатки:&#039;&#039;&#039;&lt;br /&gt;
* нет гарантии, что итеративный процесс сойдётся к оптимальному решению;&lt;br /&gt;
* производительность существенно зависит от выбора начальных кластерных центров.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
1)  [https://github.com/artpar/Hard-Clustering-implementation Последовательная реализация на С++ ]&lt;br /&gt;
&lt;br /&gt;
2) [http://projects.jasmeet.me/2013/03/HardCMeans.html Последовательная реализация на MatLab ]&lt;br /&gt;
&lt;br /&gt;
На момент публикации параллельных реализаций в свободном доступе обнаружено не было.&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Юрий Комаров</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=8136</id>
		<title>Участник:Светлана Лукьяненко/Строгий алгоритм С средних (Hard C-Means, HCM)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=8136"/>
		<updated>2016-10-14T20:40:53Z</updated>

		<summary type="html">&lt;p&gt;Юрий Комаров: /* Макроструктура алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Строгий алгоритм С средних (Hard C-Means,HCM)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;nN+1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;C(N+n)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы описания: [[Участник:Светлана_Лукьяненко|Лукьяненко Светлана]], [[Участник:Юрий_Комаров|Комаров Юрий]].&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Строгий алгоритм C средних&#039;&#039;&#039; (&#039;&#039;&#039;&#039;&#039;Hard C-Means&#039;&#039;&#039;&#039;&#039;; &#039;&#039;Jang, Sun and Mizutani, 1997&#039;&#039;) позволяет распределить большие наборы числовых данных по кластерам в многомерном пространстве&amp;lt;ref&amp;gt;Jan Jantzen «Neurofuzzy Modelling». Электронное издание.&amp;lt;/ref&amp;gt;. Алгоритм является управляемым, так как для работы с ним требуется задание одного параметра — числа кластеров, на которое необходимо разделить данные. &lt;br /&gt;
Входными данными для алгоритма являются набор векторов и количество кластеров, также может задаваться пороговое значение величины объектной функции, по достижении которого расчёт прекращается. Выходными данными для алгоритма является рядовая матрица, отображающая принадлежность исходных элементов построенным кластерам, и центры построенных кластеров.&lt;br /&gt;
&lt;br /&gt;
Первым шагом выполнения алгоритма является инициализация центров кластеров случайными значениями. Дальнейшие шаги алгоритма выполняются итеративно до тех пор, пока объектная функция не станет меньше порогового значения или же значение объектной функции не будет минимально отличаться от полученного на предыдущей итерации. На каждой итерации вычислений выполняются следующие действия:&lt;br /&gt;
&lt;br /&gt;
# Расчёт рядовой матрицы, сопоставляющей каждый вектор с ближайшим кластерным центром.&lt;br /&gt;
# Расчёт объектной функции; проверка условий остановки и завершение расчёта в случае их выполнения.&lt;br /&gt;
# Пересчёт кластерных центров.&lt;br /&gt;
&lt;br /&gt;
Так как алгоритм является итеративным и зависит от начальных значений кластерных центров, он может не сходиться к локальному минимуму.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
==== Входные и выходные данные ====&lt;br /&gt;
На вход подаётся набор векторов &amp;lt;math&amp;gt;\{u_k\}_{k=1}^{N}&amp;lt;/math&amp;gt; пространства &amp;lt;math&amp;gt;\mathbb{R}^n&amp;lt;/math&amp;gt; и количество кластеров &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Конечным результатом работы алгоритма являются построенная рядовая матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, содержащая информацию о принадлежности элементов кластерам:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ij} = \begin{cases}&lt;br /&gt;
1, &amp;amp; u_j \in C_i, \\&lt;br /&gt;
0, &amp;amp; \text{otherwise},&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; подразумевается &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый построенный кластер, и набор &amp;lt;math&amp;gt;\{c_i\}_{i=1}^{C}&amp;lt;/math&amp;gt; центров этих кластеров.&lt;br /&gt;
&lt;br /&gt;
==== Описание алгоритма ====&lt;br /&gt;
Алгоритм состоит из 5 последовательных шагов.&amp;lt;ref&amp;gt; Нейский И.М. Классификация и сравнение методов кластеризации.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 1&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация кластерных центров&#039;&#039;&#039; &amp;lt;math&amp;gt;c_i \, (i=1,2,\ldots,C)&amp;lt;/math&amp;gt; может происходить за счёт случайного выбора необходимого числа точек из входного набора либо путём явного указания.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 2&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вычисление рядовой матрицы&#039;&#039;&#039; &amp;lt;math&amp;gt;M = \|m_{ik}\|&amp;lt;/math&amp;gt;, элементы которой задаются следующими выражениями (&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; — количество элементов во входном наборе данных):&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ik} = \begin{cases}&lt;br /&gt;
1, &amp;amp; \|u_k-c_i\|^2 \leqslant \|u_k-c_j\|^2 \;\; \text{for all } i \neq j; \;\; (i,j=1,2,\ldots,C; \; k = 1,2,\ldots,N)\\&lt;br /&gt;
0, &amp;amp; \text{otherwise}.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;!-- При этом, как легко видеть, матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; обладает следующими свойствами:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\sum\limits_{i=1}^C m_{ij} = 1, \;\; \sum\limits_{i=1}^C\sum\limits_{j=1}^K m_{ij} = K.&lt;br /&gt;
&amp;lt;/math&amp;gt; --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Будем говорить, что &amp;lt;math&amp;gt;u_k \in C_i&amp;lt;/math&amp;gt;, если &amp;lt;math&amp;gt;m_{ik} = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 3&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Расчёт объектной функции:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^C J_i = \sum\limits_{i=1}^C \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right)&lt;br /&gt;
.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На этом шаге происходит &#039;&#039;&#039;&amp;lt;u&amp;gt;остановка и выход из цикла&amp;lt;/u&amp;gt;&#039;&#039;&#039;, если полученное значение ниже пороговой величины &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; или полученное значение не сильно отличается от значений, полученных на предыдущих циклах.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 4&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Пересчёт кластерных центров&#039;&#039;&#039; выполняется в соответствии со следующим уравнением:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;|C_i|&amp;lt;/math&amp;gt; подразумевается количество элементов в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом кластере.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 5&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Переход по циклу&#039;&#039;&#039; на шаг 2.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма составляют вычисления квадратов нормы расстояния от каждого из векторов исходной выборки до промежуточных кластерных центров &amp;lt;math&amp;gt;\|u_k-c_i\|^2&amp;lt;/math&amp;gt;. На каждой итерации алгоритма происходит расчёт &amp;lt;math&amp;gt;CN&amp;lt;/math&amp;gt; таких расстояний.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Основной операцией, выполняемой в алгоритме, как сказано выше, является операция нахождения квадратов расстояний между исходными векторами и кластерными центрами. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
d_{ki} = \|u_k-c_i\|^2&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также на шаге вычисления объектной функции производится множественное суммирование полученных расстояний:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^C J_i = \sum\limits_{i=1}^C \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right),&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
а на шаге расчета кластерных центров происходит суммирование векторов:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Реализация последовательного алгоритма состоит в итеративном повторении блока, описанного далее в форме псевдокода, до тех пор, пока не будет достигнута желаемая точность.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;&lt;br /&gt;
J = 0;&lt;br /&gt;
M = zeros(N,C);&lt;br /&gt;
for i = 1 to N //go through every element&lt;br /&gt;
   d_min = MAXINT;&lt;br /&gt;
   j_min = 1;&lt;br /&gt;
   for j = 1 to C //deside which claster does element belong to&lt;br /&gt;
      d_ij  = sq_norm(u[i] - c[j]);&lt;br /&gt;
      if d_ij &amp;lt; d_min&lt;br /&gt;
         d_min = d_ij;&lt;br /&gt;
         j_min = j;&lt;br /&gt;
   //generation of output data&lt;br /&gt;
   J += d_min; &lt;br /&gt;
   M[i,j_min] = 1;&lt;br /&gt;
   c_new[j] += u[i];&lt;br /&gt;
   c_newCount[k]++;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
На каждой итерации алгоритма требуется выполнение:&lt;br /&gt;
* &amp;lt;math&amp;gt;NC&amp;lt;/math&amp;gt; операций вычисления квадрата нормы разности элементов;&lt;br /&gt;
* &amp;lt;math&amp;gt;NC&amp;lt;/math&amp;gt; операций сравнения (вычитаний);&lt;br /&gt;
* &amp;lt;math&amp;gt;3N&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
&lt;br /&gt;
Каждая операция вычисления нормы разности векторов предполагает выполнение &amp;lt;math&amp;gt;2n-1&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания и &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; операций возведения в квадрат (умножений), поэтому получаем для каждой итерации:&lt;br /&gt;
* &amp;lt;math&amp;gt;(2nC + 3)N&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания;&lt;br /&gt;
* &amp;lt;math&amp;gt;nNC&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
&lt;br /&gt;
Ожидая, что предельная точность будет достигнута менее, чем за &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; итераций (в противном случае применение алгоритма можно считать нецелесообразным), получаем итоговую сложность последовательной реализации алгоритма &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt; (в предположении, что &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; существенно меньше &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Приведём аналитическое и графическое описание графа алгоритма.&lt;br /&gt;
&lt;br /&gt;
Граф алгоритма состоит из 5 различных видов вершин.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первая&#039;&#039;&#039; группа вершин отмечена символом &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039;, ей соответствует вычисление минимального расстояния до кластерных центров, включающее в себя следующую последовательность действий:&lt;br /&gt;
* независимое вычисление расстояний от заданного элемента &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; до каждого из кластерных центров;&lt;br /&gt;
* последовательное сравнение полученных значений с целью отыскания максимума;&lt;br /&gt;
* передача найденного минимального расстояния и соответствующего ему индекса кластера.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вторая&#039;&#039;&#039; группа вершин отмечена символом &#039;&#039;&#039;&#039;&#039;M&#039;&#039;&#039;&#039;&#039;, ей соответствует операция записи 1 в столбец, отвечающий ветке графа, в позицию, полученную на предыдущем шаге и соответствующую ближайшему кластерному центру.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Третья&#039;&#039;&#039; вершина отмечена символом &#039;&#039;&#039;&#039;&#039;J&#039;&#039;&#039;&#039;&#039;, подразумевается, что на этом этапе происходит расчёт объектной функции.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Четвертая&#039;&#039;&#039; вершина обозначена треугольным маркером и помечена &#039;&#039;&#039;&#039;&#039;if&#039;&#039;&#039;&#039;&#039;, на этом этапе происходит проверка условия достижения необходимой точности (условия остановки итерационного процесса).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Пятая&#039;&#039;&#039; соответствует операции пересчёта кластерных центров, она отмечена как &#039;&#039;&#039;&#039;&#039;{c}&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Все эти виды вершин визуально выделены в одну большую группу, поскольку все вместе они составляют одну полную итерацию алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:HardCMeans1.png|thumb|800px|center|Рисунок 1. Информационный граф алгоритма. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (&amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; стартовых значений кластерных центров и 1 значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; на каждую вершину графа), &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039; — вычисление минимального расстояния до кластерных центров (подробнее см. рисунок 2), &#039;&#039;&#039;&#039;&#039;M&#039;&#039;&#039;&#039;&#039; — запись единички в соответствующий столбец матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, &#039;&#039;&#039;&#039;&#039;J&#039;&#039;&#039;&#039;&#039; — вычисление объектной функции по результатам полученных вычислений, &#039;&#039;&#039;&#039;&#039;if&#039;&#039;&#039;&#039;&#039; — проверка условия достижения заданной точности, &#039;&#039;&#039;&#039;&#039;{c}&#039;&#039;&#039;&#039;&#039; — пересчёт кластерных центров и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; значений полученных кластерных центров).]]&lt;br /&gt;
[[File:HardCMeans2.PNG|thumb|400px|center|Рисунок 2. Подробное описание работы блока  &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039;. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (1 значение центра кластера на каждую из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; соответствующих вершин графа и значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;), &#039;&#039;&#039;&#039;&#039;d1,...,dC&#039;&#039;&#039;&#039;&#039; — прямое вычисление  расстояния до кластерных центров, &#039;&#039;&#039;&#039;&#039;max&#039;&#039;&#039;&#039;&#039; — вычисление максимума двух чисел (с сохранением соответствующего максимуму кластерного индекса) и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (индекс кластерного центра, расположенного ближе всего к точке &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;, и соответствующее расстояние).]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
Для выполнения одной итерации алгоритма C средних необходимо выполнить параллельно ряд вычислений для каждого из &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; элементов:&lt;br /&gt;
&lt;br /&gt;
# Вычисление &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; расстояний между элементом и кластерными центрами.&lt;br /&gt;
# Выполнение &amp;lt;math&amp;gt;(C - 1)&amp;lt;/math&amp;gt; сравнений для определения минимального.&lt;br /&gt;
# Определение значений соответствующего рассматриваемому элементу &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; столбца матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Эта последовательность операций может быть выполнена для каждого элемента &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; входной выборки независимо и поэтому составляет основной ресурс параллелизма алгоритма.&lt;br /&gt;
&lt;br /&gt;
При этом, как можно видеть из информационного графа алгоритма, часть вычислений проводится в последовательном режиме, например, расчёт значения объектной функции &amp;lt;math&amp;gt;J&amp;lt;/math&amp;gt;. Аналогичная ситуация имеет место и с пересчётом кластерных центров — разделив эту операцию на &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; независимых процессов, мы потеряем в производительности за счёт увеличения накладных расходов, связанных с пересылкой данных и координацией вычислений.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что при малом объёме выборки и размерности системы попытка использования параллельной реализации алгоритма приведёт к понижению производительности, поскольку проведение последовательных расчётов потребует меньше времени, нежели пересылка данных (хотя бы матриц размера &amp;lt;math&amp;gt;nC&amp;lt;/math&amp;gt;, определяющих кластерные центры).&lt;br /&gt;
&lt;br /&gt;
При этом, как легко видеть, ширина [[глоссарий#Ярусно-параллельная форма графа алгоритма|ЯПФ]] составляет &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt; (если быть точнее, просто &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;). Высота ЯПФ для строгого алгоритма C средних оценивается как &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt; (предполагаем, что число итераций существенно меньше объёма выборки &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; &lt;br /&gt;
*&amp;lt;math&amp;gt;\{u_k\}_{k=1}^{N} \subset \mathbb{R}^n&amp;lt;/math&amp;gt; — исходный набор векторов;&lt;br /&gt;
*&amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; — количество кластеров (&amp;lt;math&amp;gt;2 \leqslant C \leqslant N&amp;lt;/math&amp;gt;);&lt;br /&gt;
* &#039;&#039;(опционально)&#039;&#039; &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; — пороговая точность работы алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;nN+1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
*&amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; — рядовая матрица из пространства &amp;lt;math&amp;gt;\mathbb{R}^{C \times N}&amp;lt;/math&amp;gt;.&lt;br /&gt;
*&amp;lt;math&amp;gt;\{c_k\}_{k=1}^{C}&amp;lt;/math&amp;gt; — набор построенных кластерных центров.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;C(N+n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Назначение:&#039;&#039;&#039; кластеризация больших наборов числовых данных.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Достоинства:&#039;&#039;&#039;&lt;br /&gt;
* лёгкость реализации;&lt;br /&gt;
* вычислительная простота.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Недостатки:&#039;&#039;&#039;&lt;br /&gt;
* нет гарантии, что итеративный процесс сойдётся к оптимальному решению;&lt;br /&gt;
* производительность существенно зависит от выбора начальных кластерных центров.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
1)  [https://github.com/artpar/Hard-Clustering-implementation Последовательная реализация на С++ ]&lt;br /&gt;
&lt;br /&gt;
2) [http://projects.jasmeet.me/2013/03/HardCMeans.html Последовательная реализация на MatLab ]&lt;br /&gt;
&lt;br /&gt;
На момент публикации параллельных реализаций в свободном доступе обнаружено не было.&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Юрий Комаров</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=8131</id>
		<title>Участник:Светлана Лукьяненко/Строгий алгоритм С средних (Hard C-Means, HCM)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=8131"/>
		<updated>2016-10-14T20:38:07Z</updated>

		<summary type="html">&lt;p&gt;Юрий Комаров: /* Информационный граф */ Добавлено текстовое описание&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Строгий алгоритм С средних (Hard C-Means,HCM)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;nN+1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;C(N+n)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы описания: [[Участник:Светлана_Лукьяненко|Лукьяненко Светлана]], [[Участник:Юрий_Комаров|Комаров Юрий]].&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Строгий алгоритм C средних&#039;&#039;&#039; (&#039;&#039;&#039;&#039;&#039;Hard C-Means&#039;&#039;&#039;&#039;&#039;; &#039;&#039;Jang, Sun and Mizutani, 1997&#039;&#039;) позволяет распределить большие наборы числовых данных по кластерам в многомерном пространстве&amp;lt;ref&amp;gt;Jan Jantzen «Neurofuzzy Modelling». Электронное издание.&amp;lt;/ref&amp;gt;. Алгоритм является управляемым, так как для работы с ним требуется задание одного параметра — числа кластеров, на которое необходимо разделить данные. &lt;br /&gt;
Входными данными для алгоритма являются набор векторов и количество кластеров, также может задаваться пороговое значение величины объектной функции, по достижении которого расчёт прекращается. Выходными данными для алгоритма является рядовая матрица, отображающая принадлежность исходных элементов построенным кластерам, и центры построенных кластеров.&lt;br /&gt;
&lt;br /&gt;
Первым шагом выполнения алгоритма является инициализация центров кластеров случайными значениями. Дальнейшие шаги алгоритма выполняются итеративно до тех пор, пока объектная функция не станет меньше порогового значения или же значение объектной функции не будет минимально отличаться от полученного на предыдущей итерации. На каждой итерации вычислений выполняются следующие действия:&lt;br /&gt;
&lt;br /&gt;
# Расчёт рядовой матрицы, сопоставляющей каждый вектор с ближайшим кластерным центром.&lt;br /&gt;
# Расчёт объектной функции; проверка условий остановки и завершение расчёта в случае их выполнения.&lt;br /&gt;
# Пересчёт кластерных центров.&lt;br /&gt;
&lt;br /&gt;
Так как алгоритм является итеративным и зависит от начальных значений кластерных центров, он может не сходиться к локальному минимуму.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
==== Входные и выходные данные ====&lt;br /&gt;
На вход подаётся набор векторов &amp;lt;math&amp;gt;\{u_k\}_{k=1}^{N}&amp;lt;/math&amp;gt; пространства &amp;lt;math&amp;gt;\mathbb{R}^n&amp;lt;/math&amp;gt; и количество кластеров &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Конечным результатом работы алгоритма являются построенная рядовая матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, содержащая информацию о принадлежности элементов кластерам:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ij} = \begin{cases}&lt;br /&gt;
1, &amp;amp; u_j \in C_i, \\&lt;br /&gt;
0, &amp;amp; \text{otherwise},&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; подразумевается &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый построенный кластер, и набор &amp;lt;math&amp;gt;\{c_i\}_{i=1}^{C}&amp;lt;/math&amp;gt; центров этих кластеров.&lt;br /&gt;
&lt;br /&gt;
==== Описание алгоритма ====&lt;br /&gt;
Алгоритм состоит из 5 последовательных шагов.&amp;lt;ref&amp;gt; Нейский И.М. Классификация и сравнение методов кластеризации.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 1&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация кластерных центров&#039;&#039;&#039; &amp;lt;math&amp;gt;c_i \, (i=1,2,\ldots,C)&amp;lt;/math&amp;gt; может происходить за счёт случайного выбора необходимого числа точек из входного набора либо путём явного указания.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 2&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вычисление рядовой матрицы&#039;&#039;&#039; &amp;lt;math&amp;gt;M = \|m_{ik}\|&amp;lt;/math&amp;gt;, элементы которой задаются следующими выражениями (&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; — количество элементов во входном наборе данных):&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ik} = \begin{cases}&lt;br /&gt;
1, &amp;amp; \|u_k-c_i\|^2 \leqslant \|u_k-c_j\|^2 \;\; \text{for all } i \neq j; \;\; (i,j=1,2,\ldots,C; \; k = 1,2,\ldots,N)\\&lt;br /&gt;
0, &amp;amp; \text{otherwise}.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;!-- При этом, как легко видеть, матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; обладает следующими свойствами:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\sum\limits_{i=1}^C m_{ij} = 1, \;\; \sum\limits_{i=1}^C\sum\limits_{j=1}^K m_{ij} = K.&lt;br /&gt;
&amp;lt;/math&amp;gt; --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Будем говорить, что &amp;lt;math&amp;gt;u_k \in C_i&amp;lt;/math&amp;gt;, если &amp;lt;math&amp;gt;m_{ik} = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 3&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Расчёт объектной функции:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^C J_i = \sum\limits_{i=1}^C \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right)&lt;br /&gt;
.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На этом шаге происходит &#039;&#039;&#039;&amp;lt;u&amp;gt;остановка и выход из цикла&amp;lt;/u&amp;gt;&#039;&#039;&#039;, если полученное значение ниже пороговой величины &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; или полученное значение не сильно отличается от значений, полученных на предыдущих циклах.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 4&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Пересчёт кластерных центров&#039;&#039;&#039; выполняется в соответствии со следующим уравнением:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;|C_i|&amp;lt;/math&amp;gt; подразумевается количество элементов в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом кластере.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 5&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Переход по циклу&#039;&#039;&#039; на шаг 2.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма составляют вычисления квадратов нормы расстояния от каждого из векторов исходной выборки до промежуточных кластерных центров &amp;lt;math&amp;gt;\|u_k-c_i\|^2&amp;lt;/math&amp;gt;. На каждой итерации алгоритма происходит расчёт &amp;lt;math&amp;gt;CN&amp;lt;/math&amp;gt; таких расстояний.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Основной операцией, выполняемой в алгоритме, как сказано выше, является операция нахождения квадратов расстояний между векторами данных и кластерными центрами. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
d_{ki} = \|u_k-c_i\|^2&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также на шаге вычисления объектной функции производится множественное суммирование полученных расстояний:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^C J_i = \sum\limits_{i=1}^C \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right),&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
а на шаге расчета кластерных центров происходит суммирование векторов:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Реализация последовательного алгоритма состоит в итеративном повторении блока, описанного далее в форме псевдокода, до тех пор, пока не будет достигнута желаемая точность.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;&lt;br /&gt;
J = 0;&lt;br /&gt;
M = zeros(N,C);&lt;br /&gt;
for i = 1 to N //go through every element&lt;br /&gt;
   d_min = MAXINT;&lt;br /&gt;
   j_min = 1;&lt;br /&gt;
   for j = 1 to C //deside which claster does element belong to&lt;br /&gt;
      d_ij  = sq_norm(u[i] - c[j]);&lt;br /&gt;
      if d_ij &amp;lt; d_min&lt;br /&gt;
         d_min = d_ij;&lt;br /&gt;
         j_min = j;&lt;br /&gt;
   //generation of output data&lt;br /&gt;
   J += d_min; &lt;br /&gt;
   M[i,j_min] = 1;&lt;br /&gt;
   c_new[j] += u[i];&lt;br /&gt;
   c_newCount[k]++;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
На каждой итерации алгоритма требуется выполнение:&lt;br /&gt;
* &amp;lt;math&amp;gt;NC&amp;lt;/math&amp;gt; операций вычисления квадрата нормы разности элементов;&lt;br /&gt;
* &amp;lt;math&amp;gt;NC&amp;lt;/math&amp;gt; операций сравнения (вычитаний);&lt;br /&gt;
* &amp;lt;math&amp;gt;3N&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
&lt;br /&gt;
Каждая операция вычисления нормы разности векторов предполагает выполнение &amp;lt;math&amp;gt;2n-1&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания и &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; операций возведения в квадрат (умножений), поэтому получаем для каждой итерации:&lt;br /&gt;
* &amp;lt;math&amp;gt;(2nC + 3)N&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания;&lt;br /&gt;
* &amp;lt;math&amp;gt;nNC&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
&lt;br /&gt;
Ожидая, что предельная точность будет достигнута менее, чем за &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; итераций (в противном случае применение алгоритма можно считать нецелесообразным), получаем итоговую сложность последовательной реализации алгоритма &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt; (в предположении, что &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; существенно меньше &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
Приведём аналитическое и графическое описание графа алгоритма.&lt;br /&gt;
&lt;br /&gt;
Граф алгоритма состоит из 5 различных видов вершин.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первая&#039;&#039;&#039; группа вершин отмечена символом &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039;, ей соответствует вычисление минимального расстояния до кластерных центров, включающее в себя следующую последовательность действий:&lt;br /&gt;
* независимое вычисление расстояний от заданного элемента &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; до каждого из кластерных центров;&lt;br /&gt;
* последовательное сравнение полученных значений с целью отыскания максимума;&lt;br /&gt;
* передача найденного минимального расстояния и соответствующего ему индекса кластера.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вторая&#039;&#039;&#039; группа вершин отмечена символом &#039;&#039;&#039;&#039;&#039;M&#039;&#039;&#039;&#039;&#039;, ей соответствует операция записи 1 в столбец, отвечающий ветке графа, в позицию, полученную на предыдущем шаге и соответствующую ближайшему кластерному центру.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Третья&#039;&#039;&#039; вершина отмечена символом &#039;&#039;&#039;&#039;&#039;J&#039;&#039;&#039;&#039;&#039;, подразумевается, что на этом этапе происходит расчёт объектной функции.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Четвертая&#039;&#039;&#039; вершина обозначена треугольным маркером и помечена &#039;&#039;&#039;&#039;&#039;if&#039;&#039;&#039;&#039;&#039;, на этом этапе происходит проверка условия достижения необходимой точности (условия остановки итерационного процесса).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Пятая&#039;&#039;&#039; соответствует операции пересчёта кластерных центров, она отмечена как &#039;&#039;&#039;&#039;&#039;{c}&#039;&#039;&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Все эти виды вершин визуально выделены в одну большую группу, поскольку все вместе они составляют одну полную итерацию алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:HardCMeans1.png|thumb|800px|center|Рисунок 1. Информационный граф алгоритма. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (&amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; стартовых значений кластерных центров и 1 значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; на каждую вершину графа), &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039; — вычисление минимального расстояния до кластерных центров (подробнее см. рисунок 2), &#039;&#039;&#039;&#039;&#039;M&#039;&#039;&#039;&#039;&#039; — запись единички в соответствующий столбец матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, &#039;&#039;&#039;&#039;&#039;J&#039;&#039;&#039;&#039;&#039; — вычисление объектной функции по результатам полученных вычислений, &#039;&#039;&#039;&#039;&#039;if&#039;&#039;&#039;&#039;&#039; — проверка условия достижения заданной точности, &#039;&#039;&#039;&#039;&#039;{c}&#039;&#039;&#039;&#039;&#039; — пересчёт кластерных центров и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; значений полученных кластерных центров).]]&lt;br /&gt;
[[File:HardCMeans2.PNG|thumb|400px|center|Рисунок 2. Подробное описание работы блока  &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039;. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (1 значение центра кластера на каждую из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; соответствующих вершин графа и значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;), &#039;&#039;&#039;&#039;&#039;d1,...,dC&#039;&#039;&#039;&#039;&#039; — прямое вычисление  расстояния до кластерных центров, &#039;&#039;&#039;&#039;&#039;max&#039;&#039;&#039;&#039;&#039; — вычисление максимума двух чисел (с сохранением соответствующего максимуму кластерного индекса) и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (индекс кластерного центра, расположенного ближе всего к точке &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;, и соответствующее расстояние).]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
Для выполнения одной итерации алгоритма C средних необходимо выполнить параллельно ряд вычислений для каждого из &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; элементов:&lt;br /&gt;
&lt;br /&gt;
# Вычисление &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; расстояний между элементом и кластерными центрами.&lt;br /&gt;
# Выполнение &amp;lt;math&amp;gt;(C - 1)&amp;lt;/math&amp;gt; сравнений для определения минимального.&lt;br /&gt;
# Определение значений соответствующего рассматриваемому элементу &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; столбца матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Эта последовательность операций может быть выполнена для каждого элемента &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; входной выборки независимо и поэтому составляет основной ресурс параллелизма алгоритма.&lt;br /&gt;
&lt;br /&gt;
При этом, как можно видеть из информационного графа алгоритма, часть вычислений проводится в последовательном режиме, например, расчёт значения объектной функции &amp;lt;math&amp;gt;J&amp;lt;/math&amp;gt;. Аналогичная ситуация имеет место и с пересчётом кластерных центров — разделив эту операцию на &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; независимых процессов, мы потеряем в производительности за счёт увеличения накладных расходов, связанных с пересылкой данных и координацией вычислений.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что при малом объёме выборки и размерности системы попытка использования параллельной реализации алгоритма приведёт к понижению производительности, поскольку проведение последовательных расчётов потребует меньше времени, нежели пересылка данных (хотя бы матриц размера &amp;lt;math&amp;gt;nC&amp;lt;/math&amp;gt;, определяющих кластерные центры).&lt;br /&gt;
&lt;br /&gt;
При этом, как легко видеть, ширина [[глоссарий#Ярусно-параллельная форма графа алгоритма|ЯПФ]] составляет &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt; (если быть точнее, просто &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;). Высота ЯПФ для строгого алгоритма C средних оценивается как &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt; (предполагаем, что число итераций существенно меньше объёма выборки &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; &lt;br /&gt;
*&amp;lt;math&amp;gt;\{u_k\}_{k=1}^{N} \subset \mathbb{R}^n&amp;lt;/math&amp;gt; — исходный набор векторов;&lt;br /&gt;
*&amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; — количество кластеров (&amp;lt;math&amp;gt;2 \leqslant C \leqslant N&amp;lt;/math&amp;gt;);&lt;br /&gt;
* &#039;&#039;(опционально)&#039;&#039; &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; — пороговая точность работы алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;nN+1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
*&amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; — рядовая матрица из пространства &amp;lt;math&amp;gt;\mathbb{R}^{C \times N}&amp;lt;/math&amp;gt;.&lt;br /&gt;
*&amp;lt;math&amp;gt;\{c_k\}_{k=1}^{C}&amp;lt;/math&amp;gt; — набор построенных кластерных центров.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;C(N+n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Назначение:&#039;&#039;&#039; кластеризация больших наборов числовых данных.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Достоинства:&#039;&#039;&#039;&lt;br /&gt;
* лёгкость реализации;&lt;br /&gt;
* вычислительная простота.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Недостатки:&#039;&#039;&#039;&lt;br /&gt;
* нет гарантии, что итеративный процесс сойдётся к оптимальному решению;&lt;br /&gt;
* производительность существенно зависит от выбора начальных кластерных центров.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
1)  [https://github.com/artpar/Hard-Clustering-implementation Последовательная реализация на С++ ]&lt;br /&gt;
&lt;br /&gt;
2) [http://projects.jasmeet.me/2013/03/HardCMeans.html Последовательная реализация на MatLab ]&lt;br /&gt;
&lt;br /&gt;
На момент публикации параллельных реализаций в свободном доступе обнаружено не было.&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Юрий Комаров</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=8088</id>
		<title>Участник:Светлана Лукьяненко/Строгий алгоритм С средних (Hard C-Means, HCM)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=8088"/>
		<updated>2016-10-14T20:08:27Z</updated>

		<summary type="html">&lt;p&gt;Юрий Комаров: /* Существующие реализации алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Строгий алгоритм С средних (Hard C-Means,HCM)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;nN+1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;C(N+n)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы описания: [[Участник:Светлана_Лукьяненко|Лукьяненко Светлана]], [[Участник:Юрий_Комаров|Комаров Юрий]].&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Строгий алгоритм C средних&#039;&#039;&#039; (&#039;&#039;&#039;&#039;&#039;Hard C-Means&#039;&#039;&#039;&#039;&#039;; &#039;&#039;Jang, Sun and Mizutani, 1997&#039;&#039;) позволяет распределить большие наборы числовых данных по кластерам в многомерном пространстве&amp;lt;ref&amp;gt;Jan Jantzen «Neurofuzzy Modelling». Электронное издание.&amp;lt;/ref&amp;gt;. Алгоритм является управляемым, так как для работы с ним требуется задание одного параметра — числа кластеров, на которое необходимо разделить данные. &lt;br /&gt;
Входными данными для алгоритма являются набор векторов и количество кластеров, также может задаваться пороговое значение величины объектной функции, по достижении которого расчёт прекращается. Выходными данными для алгоритма является рядовая матрица, отображающая принадлежность исходных элементов построенным кластерам, и центры построенных кластеров.&lt;br /&gt;
&lt;br /&gt;
Первым шагом выполнения алгоритма является инициализация центров кластеров случайными значениями. Дальнейшие шаги алгоритма выполняются итеративно до тех пор, пока объектная функция не станет меньше порогового значения или же значение объектной функции не будет минимально отличаться от полученного на предыдущей итерации. На каждой итерации вычислений выполняются следующие действия:&lt;br /&gt;
&lt;br /&gt;
# Расчёт рядовой матрицы, сопоставляющей каждый вектор с ближайшим кластерным центром.&lt;br /&gt;
# Расчёт объектной функции; проверка условий остановки и завершение расчёта в случае их выполнения.&lt;br /&gt;
# Пересчёт кластерных центров.&lt;br /&gt;
&lt;br /&gt;
Так как алгоритм является итеративным и зависит от начальных значений кластерных центров, он может не сходиться к локальному минимуму.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
==== Входные и выходные данные ====&lt;br /&gt;
На вход подаётся набор векторов &amp;lt;math&amp;gt;\{u_k\}_{k=1}^{N}&amp;lt;/math&amp;gt; пространства &amp;lt;math&amp;gt;\mathbb{R}^n&amp;lt;/math&amp;gt; и количество кластеров &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Конечным результатом работы алгоритма являются построенная рядовая матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, содержащая информацию о принадлежности элементов кластерам:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ij} = \begin{cases}&lt;br /&gt;
1, &amp;amp; u_j \in C_i, \\&lt;br /&gt;
0, &amp;amp; \text{otherwise},&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; подразумевается &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый построенный кластер, и набор &amp;lt;math&amp;gt;\{c_i\}_{i=1}^{C}&amp;lt;/math&amp;gt; центров этих кластеров.&lt;br /&gt;
&lt;br /&gt;
==== Описание алгоритма ====&lt;br /&gt;
Алгоритм состоит из 5 последовательных шагов.&amp;lt;ref&amp;gt; Нейский И.М. Классификация и сравнение методов кластеризации.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 1&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация кластерных центров&#039;&#039;&#039; &amp;lt;math&amp;gt;c_i \, (i=1,2,\ldots,C)&amp;lt;/math&amp;gt; может происходить за счёт случайного выбора необходимого числа точек из входного набора либо путём явного указания.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 2&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вычисление рядовой матрицы&#039;&#039;&#039; &amp;lt;math&amp;gt;M = \|m_{ik}\|&amp;lt;/math&amp;gt;, элементы которой задаются следующими выражениями (&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; — количество элементов во входном наборе данных):&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ik} = \begin{cases}&lt;br /&gt;
1, &amp;amp; \|u_k-c_i\|^2 \leqslant \|u_k-c_j\|^2 \;\; \text{for all } i \neq j; \;\; (i,j=1,2,\ldots,C; \; k = 1,2,\ldots,N)\\&lt;br /&gt;
0, &amp;amp; \text{otherwise}.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;!-- При этом, как легко видеть, матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; обладает следующими свойствами:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\sum\limits_{i=1}^C m_{ij} = 1, \;\; \sum\limits_{i=1}^C\sum\limits_{j=1}^K m_{ij} = K.&lt;br /&gt;
&amp;lt;/math&amp;gt; --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Будем говорить, что &amp;lt;math&amp;gt;u_k \in C_i&amp;lt;/math&amp;gt;, если &amp;lt;math&amp;gt;m_{ik} = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 3&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Расчёт объектной функции:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^C J_i = \sum\limits_{i=1}^C \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right)&lt;br /&gt;
.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На этом шаге происходит &#039;&#039;&#039;&amp;lt;u&amp;gt;остановка и выход из цикла&amp;lt;/u&amp;gt;&#039;&#039;&#039;, если полученное значение ниже пороговой величины &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; или полученное значение не сильно отличается от значений, полученных на предыдущих циклах.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 4&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Пересчёт кластерных центров&#039;&#039;&#039; выполняется в соответствии со следующим уравнением:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;|C_i|&amp;lt;/math&amp;gt; подразумевается количество элементов в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом кластере.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 5&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Переход по циклу&#039;&#039;&#039; на шаг 2.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма составляют вычисления квадратов нормы расстояния от каждого из векторов исходной выборки до промежуточных кластерных центров &amp;lt;math&amp;gt;\|u_k-c_i\|^2&amp;lt;/math&amp;gt;. На каждой итерации алгоритма происходит расчёт &amp;lt;math&amp;gt;CN&amp;lt;/math&amp;gt; таких расстояний.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Основной операцией, выполняемой в алгоритме, как сказано выше, является операция нахождения квадратов расстояний между векторами данных и кластерными центрами. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
d_{ki} = \|u_k-c_i\|^2&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также на шаге вычисления объектной функции производится множественное суммирование полученных расстояний:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^C J_i = \sum\limits_{i=1}^C \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right),&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
а на шаге расчета кластерных центров происходит суммирование векторов:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Реализация последовательного алгоритма состоит в итеративном повторении блока, описанного далее в форме псевдокода, до тех пор, пока не будет достигнута желаемая точность.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;&lt;br /&gt;
J = 0;&lt;br /&gt;
M = zeros(N,C);&lt;br /&gt;
for i = 1 to N //go through every element&lt;br /&gt;
   d_min = MAXINT;&lt;br /&gt;
   j_min = 1;&lt;br /&gt;
   for j = 1 to C //deside which claster does element belong to&lt;br /&gt;
      d_ij  = sq_norm(u[i] - c[j]);&lt;br /&gt;
      if d_ij &amp;lt; d_min&lt;br /&gt;
         d_min = d_ij;&lt;br /&gt;
         j_min = j;&lt;br /&gt;
   //generation of output data&lt;br /&gt;
   J += d_min; &lt;br /&gt;
   M[i,j_min] = 1;&lt;br /&gt;
   c_new[j] += u[i];&lt;br /&gt;
   c_newCount[k]++;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
На каждой итерации алгоритма требуется выполнение:&lt;br /&gt;
* &amp;lt;math&amp;gt;NC&amp;lt;/math&amp;gt; операций вычисления квадрата нормы разности элементов;&lt;br /&gt;
* &amp;lt;math&amp;gt;NC&amp;lt;/math&amp;gt; операций сравнения (вычитаний);&lt;br /&gt;
* &amp;lt;math&amp;gt;3N&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
&lt;br /&gt;
Каждая операция вычисления нормы разности векторов предполагает выполнение &amp;lt;math&amp;gt;2n-1&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания и &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; операций возведения в квадрат (умножений), поэтому получаем для каждой итерации:&lt;br /&gt;
* &amp;lt;math&amp;gt;(2nC + 3)N&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания;&lt;br /&gt;
* &amp;lt;math&amp;gt;nNC&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
&lt;br /&gt;
Ожидая, что предельная точность будет достигнута менее, чем за &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; итераций (в противном случае применение алгоритма можно считать нецелесообразным), получаем итоговую сложность последовательной реализации алгоритма &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt; (в предположении, что &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; существенно меньше &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
[[File:HardCMeans1.png|thumb|800px|center|Рисунок 1. Информационный граф алгоритма. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (&amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; стартовых значений кластерных центров и 1 значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; на каждую вершину графа), &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039; — вычисление минимального расстояния до кластерных центров (подробнее см. рисунок 2), &#039;&#039;&#039;&#039;&#039;M&#039;&#039;&#039;&#039;&#039; — запись единички в соответствующую строчку матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, &#039;&#039;&#039;&#039;&#039;J&#039;&#039;&#039;&#039;&#039; — вычисление объектной функции по результатам полученных вычислений, &#039;&#039;&#039;&#039;&#039;if&#039;&#039;&#039;&#039;&#039; — проверка условия достижения заданной точности, &#039;&#039;&#039;&#039;&#039;{c}&#039;&#039;&#039;&#039;&#039; — пересчёт кластерных центров и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; значений полученных кластерных центров).]]&lt;br /&gt;
[[File:HardCMeans2.PNG|thumb|400px|center|Рисунок 2. Подробное описание работы блока  &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039;. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (1 значение центра кластера на каждую из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; соответствующих вершин графа и значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;), &#039;&#039;&#039;&#039;&#039;d1,...,dC&#039;&#039;&#039;&#039;&#039; — прямое вычисление  расстояния до кластерных центров, &#039;&#039;&#039;&#039;&#039;max&#039;&#039;&#039;&#039;&#039; — вычисление максимума двух чисел (с сохранением соответствующего максимуму кластерного индекса) и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (индекс кластерного центра, расположенного ближе всего к точке &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;, и соответствующее расстояние).]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
Для выполнения одной итерации алгоритма C средних необходимо выполнить параллельно ряд вычислений для каждого из &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; элементов:&lt;br /&gt;
&lt;br /&gt;
# Вычисление &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; расстояний между элементом и кластерными центрами.&lt;br /&gt;
# Выполнение &amp;lt;math&amp;gt;(C - 1)&amp;lt;/math&amp;gt; сравнений для определения минимального.&lt;br /&gt;
# Определение значений соответствующего рассматриваемому элементу &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; столбца матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Эта последовательность операций может быть выполнена для каждого элемента &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; входной выборки независимо и поэтому составляет основной ресурс параллелизма алгоритма.&lt;br /&gt;
&lt;br /&gt;
При этом, как можно видеть из информационного графа алгоритма, часть вычислений проводится в последовательном режиме, например, расчёт значения объектной функции &amp;lt;math&amp;gt;J&amp;lt;/math&amp;gt;. Аналогичная ситуация имеет место и с пересчётом кластерных центров — разделив эту операцию на &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; независимых процессов, мы потеряем в производительности за счёт увеличения накладных расходов, связанных с пересылкой данных и координацией вычислений.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что при малом объёме выборки и размерности системы попытка использования параллельной реализации алгоритма приведёт к понижению производительности, поскольку проведение последовательных расчётов потребует меньше времени, нежели пересылка данных (хотя бы матриц размера &amp;lt;math&amp;gt;nC&amp;lt;/math&amp;gt;, определяющих кластерные центры).&lt;br /&gt;
&lt;br /&gt;
При этом, как легко видеть, ширина [[глоссарий#Ярусно-параллельная форма графа алгоритма|ЯПФ]] составляет &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt; (если быть точнее, просто &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;). Высота ЯПФ для строгого алгоритма C средних оценивается как &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt; (предполагаем, что число итераций существенно меньше объёма выборки &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; &lt;br /&gt;
*&amp;lt;math&amp;gt;\{u_k\}_{k=1}^{N} \subset \mathbb{R}^n&amp;lt;/math&amp;gt; — исходный набор векторов;&lt;br /&gt;
*&amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; — количество кластеров (&amp;lt;math&amp;gt;2 \leqslant C \leqslant N&amp;lt;/math&amp;gt;);&lt;br /&gt;
* &#039;&#039;(опционально)&#039;&#039; &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; — пороговая точность работы алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;nN+1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
*&amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; — рядовая матрица из пространства &amp;lt;math&amp;gt;\mathbb{R}^{C \times N}&amp;lt;/math&amp;gt;.&lt;br /&gt;
*&amp;lt;math&amp;gt;\{c_k\}_{k=1}^{C}&amp;lt;/math&amp;gt; — набор построенных кластерных центров.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;C(N+n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Назначение:&#039;&#039;&#039; кластеризация больших наборов числовых данных.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Достоинства:&#039;&#039;&#039;&lt;br /&gt;
* лёгкость реализации;&lt;br /&gt;
* вычислительная простота.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Недостатки:&#039;&#039;&#039;&lt;br /&gt;
* нет гарантии, что итеративный процесс сойдётся к оптимальному решению;&lt;br /&gt;
* производительность существенно зависит от выбора начальных кластерных центров.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
1)  [https://github.com/artpar/Hard-Clustering-implementation Последовательная реализация на С++ ]&lt;br /&gt;
&lt;br /&gt;
2) [http://projects.jasmeet.me/2013/03/HardCMeans.html Последовательная реализация на MatLab ]&lt;br /&gt;
&lt;br /&gt;
На момент публикации параллельных реализаций в свободном доступе обнаружено не было.&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Юрий Комаров</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=8082</id>
		<title>Участник:Светлана Лукьяненко/Строгий алгоритм С средних (Hard C-Means, HCM)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=8082"/>
		<updated>2016-10-14T20:02:56Z</updated>

		<summary type="html">&lt;p&gt;Юрий Комаров: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Строгий алгоритм С средних (Hard C-Means,HCM)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;nN+1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;C(N+n)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы описания: [[Участник:Светлана_Лукьяненко|Лукьяненко Светлана]], [[Участник:Юрий_Комаров|Комаров Юрий]].&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Строгий алгоритм C средних&#039;&#039;&#039; (&#039;&#039;&#039;&#039;&#039;Hard C-Means&#039;&#039;&#039;&#039;&#039;; &#039;&#039;Jang, Sun and Mizutani, 1997&#039;&#039;) позволяет распределить большие наборы числовых данных по кластерам в многомерном пространстве&amp;lt;ref&amp;gt;Jan Jantzen «Neurofuzzy Modelling». Электронное издание.&amp;lt;/ref&amp;gt;. Алгоритм является управляемым, так как для работы с ним требуется задание одного параметра — числа кластеров, на которое необходимо разделить данные. &lt;br /&gt;
Входными данными для алгоритма являются набор векторов и количество кластеров, также может задаваться пороговое значение величины объектной функции, по достижении которого расчёт прекращается. Выходными данными для алгоритма является рядовая матрица, отображающая принадлежность исходных элементов построенным кластерам, и центры построенных кластеров.&lt;br /&gt;
&lt;br /&gt;
Первым шагом выполнения алгоритма является инициализация центров кластеров случайными значениями. Дальнейшие шаги алгоритма выполняются итеративно до тех пор, пока объектная функция не станет меньше порогового значения или же значение объектной функции не будет минимально отличаться от полученного на предыдущей итерации. На каждой итерации вычислений выполняются следующие действия:&lt;br /&gt;
&lt;br /&gt;
# Расчёт рядовой матрицы, сопоставляющей каждый вектор с ближайшим кластерным центром.&lt;br /&gt;
# Расчёт объектной функции; проверка условий остановки и завершение расчёта в случае их выполнения.&lt;br /&gt;
# Пересчёт кластерных центров.&lt;br /&gt;
&lt;br /&gt;
Так как алгоритм является итеративным и зависит от начальных значений кластерных центров, он может не сходиться к локальному минимуму.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
==== Входные и выходные данные ====&lt;br /&gt;
На вход подаётся набор векторов &amp;lt;math&amp;gt;\{u_k\}_{k=1}^{N}&amp;lt;/math&amp;gt; пространства &amp;lt;math&amp;gt;\mathbb{R}^n&amp;lt;/math&amp;gt; и количество кластеров &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Конечным результатом работы алгоритма являются построенная рядовая матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, содержащая информацию о принадлежности элементов кластерам:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ij} = \begin{cases}&lt;br /&gt;
1, &amp;amp; u_j \in C_i, \\&lt;br /&gt;
0, &amp;amp; \text{otherwise},&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; подразумевается &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый построенный кластер, и набор &amp;lt;math&amp;gt;\{c_i\}_{i=1}^{C}&amp;lt;/math&amp;gt; центров этих кластеров.&lt;br /&gt;
&lt;br /&gt;
==== Описание алгоритма ====&lt;br /&gt;
Алгоритм состоит из 5 последовательных шагов.&amp;lt;ref&amp;gt; Нейский И.М. Классификация и сравнение методов кластеризации.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 1&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация кластерных центров&#039;&#039;&#039; &amp;lt;math&amp;gt;c_i \, (i=1,2,\ldots,C)&amp;lt;/math&amp;gt; может происходить за счёт случайного выбора необходимого числа точек из входного набора либо путём явного указания.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 2&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вычисление рядовой матрицы&#039;&#039;&#039; &amp;lt;math&amp;gt;M = \|m_{ik}\|&amp;lt;/math&amp;gt;, элементы которой задаются следующими выражениями (&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; — количество элементов во входном наборе данных):&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ik} = \begin{cases}&lt;br /&gt;
1, &amp;amp; \|u_k-c_i\|^2 \leqslant \|u_k-c_j\|^2 \;\; \text{for all } i \neq j; \;\; (i,j=1,2,\ldots,C; \; k = 1,2,\ldots,N)\\&lt;br /&gt;
0, &amp;amp; \text{otherwise}.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;!-- При этом, как легко видеть, матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; обладает следующими свойствами:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\sum\limits_{i=1}^C m_{ij} = 1, \;\; \sum\limits_{i=1}^C\sum\limits_{j=1}^K m_{ij} = K.&lt;br /&gt;
&amp;lt;/math&amp;gt; --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Будем говорить, что &amp;lt;math&amp;gt;u_k \in C_i&amp;lt;/math&amp;gt;, если &amp;lt;math&amp;gt;m_{ik} = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 3&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Расчёт объектной функции:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^C J_i = \sum\limits_{i=1}^C \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right)&lt;br /&gt;
.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На этом шаге происходит &#039;&#039;&#039;&amp;lt;u&amp;gt;остановка и выход из цикла&amp;lt;/u&amp;gt;&#039;&#039;&#039;, если полученное значение ниже пороговой величины &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; или полученное значение не сильно отличается от значений, полученных на предыдущих циклах.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 4&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Пересчёт кластерных центров&#039;&#039;&#039; выполняется в соответствии со следующим уравнением:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;|C_i|&amp;lt;/math&amp;gt; подразумевается количество элементов в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом кластере.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 5&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Переход по циклу&#039;&#039;&#039; на шаг 2.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма составляют вычисления квадратов нормы расстояния от каждого из векторов исходной выборки до промежуточных кластерных центров &amp;lt;math&amp;gt;\|u_k-c_i\|^2&amp;lt;/math&amp;gt;. На каждой итерации алгоритма происходит расчёт &amp;lt;math&amp;gt;CN&amp;lt;/math&amp;gt; таких расстояний.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Основной операцией, выполняемой в алгоритме, как сказано выше, является операция нахождения квадратов расстояний между векторами данных и кластерными центрами. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
d_{ki} = \|u_k-c_i\|^2&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также на шаге вычисления объектной функции производится множественное суммирование полученных расстояний:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^C J_i = \sum\limits_{i=1}^C \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right),&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
а на шаге расчета кластерных центров происходит суммирование векторов:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Реализация последовательного алгоритма состоит в итеративном повторении блока, описанного далее в форме псевдокода, до тех пор, пока не будет достигнута желаемая точность.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;&lt;br /&gt;
J = 0;&lt;br /&gt;
M = zeros(N,C);&lt;br /&gt;
for i = 1 to N //go through every element&lt;br /&gt;
   d_min = MAXINT;&lt;br /&gt;
   j_min = 1;&lt;br /&gt;
   for j = 1 to C //deside which claster does element belong to&lt;br /&gt;
      d_ij  = sq_norm(u[i] - c[j]);&lt;br /&gt;
      if d_ij &amp;lt; d_min&lt;br /&gt;
         d_min = d_ij;&lt;br /&gt;
         j_min = j;&lt;br /&gt;
   //generation of output data&lt;br /&gt;
   J += d_min; &lt;br /&gt;
   M[i,j_min] = 1;&lt;br /&gt;
   c_new[j] += u[i];&lt;br /&gt;
   c_newCount[k]++;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
На каждой итерации алгоритма требуется выполнение:&lt;br /&gt;
* &amp;lt;math&amp;gt;NC&amp;lt;/math&amp;gt; операций вычисления квадрата нормы разности элементов;&lt;br /&gt;
* &amp;lt;math&amp;gt;NC&amp;lt;/math&amp;gt; операций сравнения (вычитаний);&lt;br /&gt;
* &amp;lt;math&amp;gt;3N&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
&lt;br /&gt;
Каждая операция вычисления нормы разности векторов предполагает выполнение &amp;lt;math&amp;gt;2n-1&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания и &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; операций возведения в квадрат (умножений), поэтому получаем для каждой итерации:&lt;br /&gt;
* &amp;lt;math&amp;gt;(2nC + 3)N&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания;&lt;br /&gt;
* &amp;lt;math&amp;gt;nNC&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
&lt;br /&gt;
Ожидая, что предельная точность будет достигнута менее, чем за &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; итераций (в противном случае применение алгоритма можно считать нецелесообразным), получаем итоговую сложность последовательной реализации алгоритма &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt; (в предположении, что &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; существенно меньше &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
[[File:HardCMeans1.png|thumb|800px|center|Рисунок 1. Информационный граф алгоритма. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (&amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; стартовых значений кластерных центров и 1 значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; на каждую вершину графа), &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039; — вычисление минимального расстояния до кластерных центров (подробнее см. рисунок 2), &#039;&#039;&#039;&#039;&#039;M&#039;&#039;&#039;&#039;&#039; — запись единички в соответствующую строчку матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, &#039;&#039;&#039;&#039;&#039;J&#039;&#039;&#039;&#039;&#039; — вычисление объектной функции по результатам полученных вычислений, &#039;&#039;&#039;&#039;&#039;if&#039;&#039;&#039;&#039;&#039; — проверка условия достижения заданной точности, &#039;&#039;&#039;&#039;&#039;{c}&#039;&#039;&#039;&#039;&#039; — пересчёт кластерных центров и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; значений полученных кластерных центров).]]&lt;br /&gt;
[[File:HardCMeans2.PNG|thumb|400px|center|Рисунок 2. Подробное описание работы блока  &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039;. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (1 значение центра кластера на каждую из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; соответствующих вершин графа и значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;), &#039;&#039;&#039;&#039;&#039;d1,...,dC&#039;&#039;&#039;&#039;&#039; — прямое вычисление  расстояния до кластерных центров, &#039;&#039;&#039;&#039;&#039;max&#039;&#039;&#039;&#039;&#039; — вычисление максимума двух чисел (с сохранением соответствующего максимуму кластерного индекса) и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (индекс кластерного центра, расположенного ближе всего к точке &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;, и соответствующее расстояние).]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
Для выполнения одной итерации алгоритма C средних необходимо выполнить параллельно ряд вычислений для каждого из &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; элементов:&lt;br /&gt;
&lt;br /&gt;
# Вычисление &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; расстояний между элементом и кластерными центрами.&lt;br /&gt;
# Выполнение &amp;lt;math&amp;gt;(C - 1)&amp;lt;/math&amp;gt; сравнений для определения минимального.&lt;br /&gt;
# Определение значений соответствующего рассматриваемому элементу &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; столбца матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Эта последовательность операций может быть выполнена для каждого элемента &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; входной выборки независимо и поэтому составляет основной ресурс параллелизма алгоритма.&lt;br /&gt;
&lt;br /&gt;
При этом, как можно видеть из информационного графа алгоритма, часть вычислений проводится в последовательном режиме, например, расчёт значения объектной функции &amp;lt;math&amp;gt;J&amp;lt;/math&amp;gt;. Аналогичная ситуация имеет место и с пересчётом кластерных центров — разделив эту операцию на &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; независимых процессов, мы потеряем в производительности за счёт увеличения накладных расходов, связанных с пересылкой данных и координацией вычислений.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что при малом объёме выборки и размерности системы попытка использования параллельной реализации алгоритма приведёт к понижению производительности, поскольку проведение последовательных расчётов потребует меньше времени, нежели пересылка данных (хотя бы матриц размера &amp;lt;math&amp;gt;nC&amp;lt;/math&amp;gt;, определяющих кластерные центры).&lt;br /&gt;
&lt;br /&gt;
При этом, как легко видеть, ширина [[глоссарий#Ярусно-параллельная форма графа алгоритма|ЯПФ]] составляет &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt; (если быть точнее, просто &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;). Высота ЯПФ для строгого алгоритма C средних оценивается как &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt; (предполагаем, что число итераций существенно меньше объёма выборки &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; &lt;br /&gt;
*&amp;lt;math&amp;gt;\{u_k\}_{k=1}^{N} \subset \mathbb{R}^n&amp;lt;/math&amp;gt; — исходный набор векторов;&lt;br /&gt;
*&amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; — количество кластеров (&amp;lt;math&amp;gt;2 \leqslant C \leqslant N&amp;lt;/math&amp;gt;);&lt;br /&gt;
* &#039;&#039;(опционально)&#039;&#039; &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; — пороговая точность работы алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;nN+1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
*&amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; — рядовая матрица из пространства &amp;lt;math&amp;gt;\mathbb{R}^{C \times N}&amp;lt;/math&amp;gt;.&lt;br /&gt;
*&amp;lt;math&amp;gt;\{c_k\}_{k=1}^{C}&amp;lt;/math&amp;gt; — набор построенных кластерных центров.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;C(N+n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Назначение:&#039;&#039;&#039; кластеризация больших наборов числовых данных.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Достоинства:&#039;&#039;&#039;&lt;br /&gt;
* лёгкость реализации;&lt;br /&gt;
* вычислительная простота.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Недостатки:&#039;&#039;&#039;&lt;br /&gt;
* нет гарантии, что итеративный процесс сойдётся к оптимальному решению;&lt;br /&gt;
* производительность существенно зависит от выбора начальных кластерных центров.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
1)  [https://github.com/artpar/Hard-Clustering-implementation Последовательная реализация на С++ ]&lt;br /&gt;
&lt;br /&gt;
2) [http://projects.jasmeet.me/2013/03/HardCMeans.html Последовательная реализация на MatLab ]&lt;br /&gt;
&lt;br /&gt;
Параллельных реализаций в свободном доступе обнаружено не было.&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Юрий Комаров</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=8081</id>
		<title>Участник:Светлана Лукьяненко/Строгий алгоритм С средних (Hard C-Means, HCM)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=8081"/>
		<updated>2016-10-14T20:01:42Z</updated>

		<summary type="html">&lt;p&gt;Юрий Комаров: /* Ресурс параллелизма алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Строгий алгоритм С средних (Hard C-Means,HCM)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;-&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;-&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;nN+1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;C(N+n)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы описания: [[Участник:Светлана_Лукьяненко|Лукьяненко Светлана]], [[Участник:Юрий_Комаров|Комаров Юрий]].&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Строгий алгоритм C средних&#039;&#039;&#039; (&#039;&#039;&#039;&#039;&#039;Hard C-Means&#039;&#039;&#039;&#039;&#039;; &#039;&#039;Jang, Sun and Mizutani, 1997&#039;&#039;) позволяет распределить большие наборы числовых данных по кластерам в многомерном пространстве&amp;lt;ref&amp;gt;Jan Jantzen «Neurofuzzy Modelling». Электронное издание.&amp;lt;/ref&amp;gt;. Алгоритм является управляемым, так как для работы с ним требуется задание одного параметра — числа кластеров, на которое необходимо разделить данные. &lt;br /&gt;
Входными данными для алгоритма являются набор векторов и количество кластеров, также может задаваться пороговое значение величины объектной функции, по достижении которого расчёт прекращается. Выходными данными для алгоритма является рядовая матрица, отображающая принадлежность исходных элементов построенным кластерам, и центры построенных кластеров.&lt;br /&gt;
&lt;br /&gt;
Первым шагом выполнения алгоритма является инициализация центров кластеров случайными значениями. Дальнейшие шаги алгоритма выполняются итеративно до тех пор, пока объектная функция не станет меньше порогового значения или же значение объектной функции не будет минимально отличаться от полученного на предыдущей итерации. На каждой итерации вычислений выполняются следующие действия:&lt;br /&gt;
&lt;br /&gt;
# Расчёт рядовой матрицы, сопоставляющей каждый вектор с ближайшим кластерным центром.&lt;br /&gt;
# Расчёт объектной функции; проверка условий остановки и завершение расчёта в случае их выполнения.&lt;br /&gt;
# Пересчёт кластерных центров.&lt;br /&gt;
&lt;br /&gt;
Так как алгоритм является итеративным и зависит от начальных значений кластерных центров, он может не сходиться к локальному минимуму.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
==== Входные и выходные данные ====&lt;br /&gt;
На вход подаётся набор векторов &amp;lt;math&amp;gt;\{u_k\}_{k=1}^{N}&amp;lt;/math&amp;gt; пространства &amp;lt;math&amp;gt;\mathbb{R}^n&amp;lt;/math&amp;gt; и количество кластеров &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Конечным результатом работы алгоритма являются построенная рядовая матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, содержащая информацию о принадлежности элементов кластерам:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ij} = \begin{cases}&lt;br /&gt;
1, &amp;amp; u_j \in C_i, \\&lt;br /&gt;
0, &amp;amp; \text{otherwise},&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; подразумевается &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый построенный кластер, и набор &amp;lt;math&amp;gt;\{c_i\}_{i=1}^{C}&amp;lt;/math&amp;gt; центров этих кластеров.&lt;br /&gt;
&lt;br /&gt;
==== Описание алгоритма ====&lt;br /&gt;
Алгоритм состоит из 5 последовательных шагов.&amp;lt;ref&amp;gt; Нейский И.М. Классификация и сравнение методов кластеризации.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 1&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация кластерных центров&#039;&#039;&#039; &amp;lt;math&amp;gt;c_i \, (i=1,2,\ldots,C)&amp;lt;/math&amp;gt; может происходить за счёт случайного выбора необходимого числа точек из входного набора либо путём явного указания.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 2&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вычисление рядовой матрицы&#039;&#039;&#039; &amp;lt;math&amp;gt;M = \|m_{ik}\|&amp;lt;/math&amp;gt;, элементы которой задаются следующими выражениями (&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; — количество элементов во входном наборе данных):&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ik} = \begin{cases}&lt;br /&gt;
1, &amp;amp; \|u_k-c_i\|^2 \leqslant \|u_k-c_j\|^2 \;\; \text{for all } i \neq j; \;\; (i,j=1,2,\ldots,C; \; k = 1,2,\ldots,N)\\&lt;br /&gt;
0, &amp;amp; \text{otherwise}.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;!-- При этом, как легко видеть, матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; обладает следующими свойствами:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\sum\limits_{i=1}^C m_{ij} = 1, \;\; \sum\limits_{i=1}^C\sum\limits_{j=1}^K m_{ij} = K.&lt;br /&gt;
&amp;lt;/math&amp;gt; --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Будем говорить, что &amp;lt;math&amp;gt;u_k \in C_i&amp;lt;/math&amp;gt;, если &amp;lt;math&amp;gt;m_{ik} = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 3&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Расчёт объектной функции:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^C J_i = \sum\limits_{i=1}^C \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right)&lt;br /&gt;
.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На этом шаге происходит &#039;&#039;&#039;&amp;lt;u&amp;gt;остановка и выход из цикла&amp;lt;/u&amp;gt;&#039;&#039;&#039;, если полученное значение ниже пороговой величины &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; или полученное значение не сильно отличается от значений, полученных на предыдущих циклах.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 4&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Пересчёт кластерных центров&#039;&#039;&#039; выполняется в соответствии со следующим уравнением:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;|C_i|&amp;lt;/math&amp;gt; подразумевается количество элементов в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом кластере.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 5&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Переход по циклу&#039;&#039;&#039; на шаг 2.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма составляют вычисления квадратов нормы расстояния от каждого из векторов исходной выборки до промежуточных кластерных центров &amp;lt;math&amp;gt;\|u_k-c_i\|^2&amp;lt;/math&amp;gt;. На каждой итерации алгоритма происходит расчёт &amp;lt;math&amp;gt;CN&amp;lt;/math&amp;gt; таких расстояний.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Основной операцией, выполняемой в алгоритме, как сказано выше, является операция нахождения квадратов расстояний между векторами данных и кластерными центрами. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
d_{ki} = \|u_k-c_i\|^2&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также на шаге вычисления объектной функции производится множественное суммирование полученных расстояний:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^C J_i = \sum\limits_{i=1}^C \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right),&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
а на шаге расчета кластерных центров происходит суммирование векторов:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Реализация последовательного алгоритма состоит в итеративном повторении блока, описанного далее в форме псевдокода, до тех пор, пока не будет достигнута желаемая точность.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;&lt;br /&gt;
J = 0;&lt;br /&gt;
M = zeros(N,C);&lt;br /&gt;
for i = 1 to N //go through every element&lt;br /&gt;
   d_min = MAXINT;&lt;br /&gt;
   j_min = 1;&lt;br /&gt;
   for j = 1 to C //deside which claster does element belong to&lt;br /&gt;
      d_ij  = sq_norm(u[i] - c[j]);&lt;br /&gt;
      if d_ij &amp;lt; d_min&lt;br /&gt;
         d_min = d_ij;&lt;br /&gt;
         j_min = j;&lt;br /&gt;
   //generation of output data&lt;br /&gt;
   J += d_min; &lt;br /&gt;
   M[i,j_min] = 1;&lt;br /&gt;
   c_new[j] += u[i];&lt;br /&gt;
   c_newCount[k]++;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
На каждой итерации алгоритма требуется выполнение:&lt;br /&gt;
* &amp;lt;math&amp;gt;NC&amp;lt;/math&amp;gt; операций вычисления квадрата нормы разности элементов;&lt;br /&gt;
* &amp;lt;math&amp;gt;NC&amp;lt;/math&amp;gt; операций сравнения (вычитаний);&lt;br /&gt;
* &amp;lt;math&amp;gt;3N&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
&lt;br /&gt;
Каждая операция вычисления нормы разности векторов предполагает выполнение &amp;lt;math&amp;gt;2n-1&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания и &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; операций возведения в квадрат (умножений), поэтому получаем для каждой итерации:&lt;br /&gt;
* &amp;lt;math&amp;gt;(2nC + 3)N&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания;&lt;br /&gt;
* &amp;lt;math&amp;gt;nNC&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
&lt;br /&gt;
Ожидая, что предельная точность будет достигнута менее, чем за &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; итераций (в противном случае применение алгоритма можно считать нецелесообразным), получаем итоговую сложность последовательной реализации алгоритма &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt; (в предположении, что &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; существенно меньше &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
[[File:HardCMeans1.png|thumb|800px|center|Рисунок 1. Информационный граф алгоритма. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (&amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; стартовых значений кластерных центров и 1 значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; на каждую вершину графа), &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039; — вычисление минимального расстояния до кластерных центров (подробнее см. рисунок 2), &#039;&#039;&#039;&#039;&#039;M&#039;&#039;&#039;&#039;&#039; — запись единички в соответствующую строчку матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, &#039;&#039;&#039;&#039;&#039;J&#039;&#039;&#039;&#039;&#039; — вычисление объектной функции по результатам полученных вычислений, &#039;&#039;&#039;&#039;&#039;if&#039;&#039;&#039;&#039;&#039; — проверка условия достижения заданной точности, &#039;&#039;&#039;&#039;&#039;{c}&#039;&#039;&#039;&#039;&#039; — пересчёт кластерных центров и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; значений полученных кластерных центров).]]&lt;br /&gt;
[[File:HardCMeans2.PNG|thumb|400px|center|Рисунок 2. Подробное описание работы блока  &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039;. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (1 значение центра кластера на каждую из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; соответствующих вершин графа и значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;), &#039;&#039;&#039;&#039;&#039;d1,...,dC&#039;&#039;&#039;&#039;&#039; — прямое вычисление  расстояния до кластерных центров, &#039;&#039;&#039;&#039;&#039;max&#039;&#039;&#039;&#039;&#039; — вычисление максимума двух чисел (с сохранением соответствующего максимуму кластерного индекса) и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (индекс кластерного центра, расположенного ближе всего к точке &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;, и соответствующее расстояние).]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
Для выполнения одной итерации алгоритма C средних необходимо выполнить параллельно ряд вычислений для каждого из &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; элементов:&lt;br /&gt;
&lt;br /&gt;
# Вычисление &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; расстояний между элементом и кластерными центрами.&lt;br /&gt;
# Выполнение &amp;lt;math&amp;gt;(C - 1)&amp;lt;/math&amp;gt; сравнений для определения минимального.&lt;br /&gt;
# Определение значений соответствующего рассматриваемому элементу &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; столбца матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Эта последовательность операций может быть выполнена для каждого элемента &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; входной выборки независимо и поэтому составляет основной ресурс параллелизма алгоритма.&lt;br /&gt;
&lt;br /&gt;
При этом, как можно видеть из информационного графа алгоритма, часть вычислений проводится в последовательном режиме, например, расчёт значения объектной функции &amp;lt;math&amp;gt;J&amp;lt;/math&amp;gt;. Аналогичная ситуация имеет место и с пересчётом кластерных центров — разделив эту операцию на &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; независимых процессов, мы потеряем в производительности за счёт увеличения накладных расходов, связанных с пересылкой данных и координацией вычислений.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что при малом объёме выборки и размерности системы попытка использования параллельной реализации алгоритма приведёт к понижению производительности, поскольку проведение последовательных расчётов потребует меньше времени, нежели пересылка данных (хотя бы матриц размера &amp;lt;math&amp;gt;nC&amp;lt;/math&amp;gt;, определяющих кластерные центры).&lt;br /&gt;
&lt;br /&gt;
При этом, как легко видеть, ширина [[глоссарий#Ярусно-параллельная форма графа алгоритма|ЯПФ]] составляет &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt; (если быть точнее, просто &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;). Высота ЯПФ для строгого алгоритма C средних оценивается как &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt; (предполагаем, что число итераций существенно меньше объёма выборки &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; &lt;br /&gt;
*&amp;lt;math&amp;gt;\{u_k\}_{k=1}^{N} \subset \mathbb{R}^n&amp;lt;/math&amp;gt; — исходный набор векторов;&lt;br /&gt;
*&amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; — количество кластеров (&amp;lt;math&amp;gt;2 \leqslant C \leqslant N&amp;lt;/math&amp;gt;);&lt;br /&gt;
* &#039;&#039;(опционально)&#039;&#039; &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; — пороговая точность работы алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;nN+1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
*&amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; — рядовая матрица из пространства &amp;lt;math&amp;gt;\mathbb{R}^{C \times N}&amp;lt;/math&amp;gt;.&lt;br /&gt;
*&amp;lt;math&amp;gt;\{c_k\}_{k=1}^{C}&amp;lt;/math&amp;gt; — набор построенных кластерных центров.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;C(N+n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Назначение:&#039;&#039;&#039; кластеризация больших наборов числовых данных.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Достоинства:&#039;&#039;&#039;&lt;br /&gt;
* лёгкость реализации;&lt;br /&gt;
* вычислительная простота.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Недостатки:&#039;&#039;&#039;&lt;br /&gt;
* нет гарантии, что итеративный процесс сойдётся к оптимальному решению;&lt;br /&gt;
* производительность существенно зависит от выбора начальных кластерных центров.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
1)  [https://github.com/artpar/Hard-Clustering-implementation Последовательная реализация на С++ ]&lt;br /&gt;
&lt;br /&gt;
2) [http://projects.jasmeet.me/2013/03/HardCMeans.html Последовательная реализация на MatLab ]&lt;br /&gt;
&lt;br /&gt;
Параллельных реализаций в свободном доступе обнаружено не было.&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Юрий Комаров</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=8063</id>
		<title>Участник:Светлана Лукьяненко/Строгий алгоритм С средних (Hard C-Means, HCM)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=8063"/>
		<updated>2016-10-14T19:47:12Z</updated>

		<summary type="html">&lt;p&gt;Юрий Комаров: /* Последовательная сложность алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Строгий алгоритм С средних (Hard C-Means,HCM)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;-&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;-&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;nN+1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;C(N+n)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы описания: [[Участник:Светлана_Лукьяненко|Лукьяненко Светлана]], [[Участник:Юрий_Комаров|Комаров Юрий]].&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Строгий алгоритм C средних&#039;&#039;&#039; (&#039;&#039;&#039;&#039;&#039;Hard C-Means&#039;&#039;&#039;&#039;&#039;; &#039;&#039;Jang, Sun and Mizutani, 1997&#039;&#039;) позволяет распределить большие наборы числовых данных по кластерам в многомерном пространстве&amp;lt;ref&amp;gt;Jan Jantzen «Neurofuzzy Modelling». Электронное издание.&amp;lt;/ref&amp;gt;. Алгоритм является управляемым, так как для работы с ним требуется задание одного параметра — числа кластеров, на которое необходимо разделить данные. &lt;br /&gt;
Входными данными для алгоритма являются набор векторов и количество кластеров, также может задаваться пороговое значение величины объектной функции, по достижении которого расчёт прекращается. Выходными данными для алгоритма является рядовая матрица, отображающая принадлежность исходных элементов построенным кластерам, и центры построенных кластеров.&lt;br /&gt;
&lt;br /&gt;
Первым шагом выполнения алгоритма является инициализация центров кластеров случайными значениями. Дальнейшие шаги алгоритма выполняются итеративно до тех пор, пока объектная функция не станет меньше порогового значения или же значение объектной функции не будет минимально отличаться от полученного на предыдущей итерации. На каждой итерации вычислений выполняются следующие действия:&lt;br /&gt;
&lt;br /&gt;
# Расчёт рядовой матрицы, сопоставляющей каждый вектор с ближайшим кластерным центром.&lt;br /&gt;
# Расчёт объектной функции; проверка условий остановки и завершение расчёта в случае их выполнения.&lt;br /&gt;
# Пересчёт кластерных центров.&lt;br /&gt;
&lt;br /&gt;
Так как алгоритм является итеративным и зависит от начальных значений кластерных центров, он может не сходиться к локальному минимуму.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
==== Входные и выходные данные ====&lt;br /&gt;
На вход подаётся набор векторов &amp;lt;math&amp;gt;\{u_k\}_{k=1}^{N}&amp;lt;/math&amp;gt; пространства &amp;lt;math&amp;gt;\mathbb{R}^n&amp;lt;/math&amp;gt; и количество кластеров &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Конечным результатом работы алгоритма являются построенная рядовая матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, содержащая информацию о принадлежности элементов кластерам:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ij} = \begin{cases}&lt;br /&gt;
1, &amp;amp; u_j \in C_i, \\&lt;br /&gt;
0, &amp;amp; \text{otherwise},&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; подразумевается &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый построенный кластер, и набор &amp;lt;math&amp;gt;\{c_i\}_{i=1}^{C}&amp;lt;/math&amp;gt; центров этих кластеров.&lt;br /&gt;
&lt;br /&gt;
==== Описание алгоритма ====&lt;br /&gt;
Алгоритм состоит из 5 последовательных шагов.&amp;lt;ref&amp;gt; Нейский И.М. Классификация и сравнение методов кластеризации.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 1&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация кластерных центров&#039;&#039;&#039; &amp;lt;math&amp;gt;c_i \, (i=1,2,\ldots,C)&amp;lt;/math&amp;gt; может происходить за счёт случайного выбора необходимого числа точек из входного набора либо путём явного указания.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 2&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вычисление рядовой матрицы&#039;&#039;&#039; &amp;lt;math&amp;gt;M = \|m_{ik}\|&amp;lt;/math&amp;gt;, элементы которой задаются следующими выражениями (&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; — количество элементов во входном наборе данных):&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ik} = \begin{cases}&lt;br /&gt;
1, &amp;amp; \|u_k-c_i\|^2 \leqslant \|u_k-c_j\|^2 \;\; \text{for all } i \neq j; \;\; (i,j=1,2,\ldots,C; \; k = 1,2,\ldots,N)\\&lt;br /&gt;
0, &amp;amp; \text{otherwise}.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;!-- При этом, как легко видеть, матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; обладает следующими свойствами:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\sum\limits_{i=1}^C m_{ij} = 1, \;\; \sum\limits_{i=1}^C\sum\limits_{j=1}^K m_{ij} = K.&lt;br /&gt;
&amp;lt;/math&amp;gt; --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Будем говорить, что &amp;lt;math&amp;gt;u_k \in C_i&amp;lt;/math&amp;gt;, если &amp;lt;math&amp;gt;m_{ik} = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 3&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Расчёт объектной функции:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^C J_i = \sum\limits_{i=1}^C \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right)&lt;br /&gt;
.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На этом шаге происходит &#039;&#039;&#039;&amp;lt;u&amp;gt;остановка и выход из цикла&amp;lt;/u&amp;gt;&#039;&#039;&#039;, если полученное значение ниже пороговой величины &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; или полученное значение не сильно отличается от значений, полученных на предыдущих циклах.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 4&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Пересчёт кластерных центров&#039;&#039;&#039; выполняется в соответствии со следующим уравнением:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;|C_i|&amp;lt;/math&amp;gt; подразумевается количество элементов в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом кластере.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 5&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Переход по циклу&#039;&#039;&#039; на шаг 2.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма составляют вычисления квадратов нормы расстояния от каждого из векторов исходной выборки до промежуточных кластерных центров &amp;lt;math&amp;gt;\|u_k-c_i\|^2&amp;lt;/math&amp;gt;. На каждой итерации алгоритма происходит расчёт &amp;lt;math&amp;gt;CN&amp;lt;/math&amp;gt; таких расстояний.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Основной операцией, выполняемой в алгоритме, как сказано выше, является операция нахождения квадратов расстояний между векторами данных и кластерными центрами. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
d_{ki} = \|u_k-c_i\|^2&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также на шаге вычисления объектной функции производится множественное суммирование полученных расстояний:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^C J_i = \sum\limits_{i=1}^C \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right),&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
а на шаге расчета кластерных центров происходит суммирование векторов:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Реализация последовательного алгоритма состоит в итеративном повторении блока, описанного далее в форме псевдокода, до тех пор, пока не будет достигнута желаемая точность.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;&lt;br /&gt;
J = 0;&lt;br /&gt;
M = zeros(N,C);&lt;br /&gt;
for i = 1 to N //go through every element&lt;br /&gt;
   d_min = MAXINT;&lt;br /&gt;
   j_min = 1;&lt;br /&gt;
   for j = 1 to C //deside which claster does element belong to&lt;br /&gt;
      d_ij  = sq_norm(u[i] - c[j]);&lt;br /&gt;
      if d_ij &amp;lt; d_min&lt;br /&gt;
         d_min = d_ij;&lt;br /&gt;
         j_min = j;&lt;br /&gt;
   //generation of output data&lt;br /&gt;
   J += d_min; &lt;br /&gt;
   M[i,j_min] = 1;&lt;br /&gt;
   c_new[j] += u[i];&lt;br /&gt;
   c_newCount[k]++;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
На каждой итерации алгоритма требуется выполнение:&lt;br /&gt;
* &amp;lt;math&amp;gt;NC&amp;lt;/math&amp;gt; операций вычисления квадрата нормы разности элементов;&lt;br /&gt;
* &amp;lt;math&amp;gt;NC&amp;lt;/math&amp;gt; операций сравнения (вычитаний);&lt;br /&gt;
* &amp;lt;math&amp;gt;3N&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
&lt;br /&gt;
Каждая операция вычисления нормы разности векторов предполагает выполнение &amp;lt;math&amp;gt;2n-1&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания и &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; операций возведения в квадрат (умножений), поэтому получаем для каждой итерации:&lt;br /&gt;
* &amp;lt;math&amp;gt;(2nC + 3)N&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания;&lt;br /&gt;
* &amp;lt;math&amp;gt;nNC&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
&lt;br /&gt;
Ожидая, что предельная точность будет достигнута менее, чем за &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; итераций (в противном случае применение алгоритма можно считать нецелесообразным), получаем итоговую сложность последовательной реализации алгоритма &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt; (в предположении, что &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; существенно меньше &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
[[File:HardCMeans1.png|thumb|800px|center|Рисунок 1. Информационный граф алгоритма. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (&amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; стартовых значений кластерных центров и 1 значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; на каждую вершину графа), &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039; — вычисление минимального расстояния до кластерных центров (подробнее см. рисунок 2), &#039;&#039;&#039;&#039;&#039;M&#039;&#039;&#039;&#039;&#039; — запись единички в соответствующую строчку матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, &#039;&#039;&#039;&#039;&#039;J&#039;&#039;&#039;&#039;&#039; — вычисление объектной функции по результатам полученных вычислений, &#039;&#039;&#039;&#039;&#039;if&#039;&#039;&#039;&#039;&#039; — проверка условия достижения заданной точности, &#039;&#039;&#039;&#039;&#039;{c}&#039;&#039;&#039;&#039;&#039; — пересчёт кластерных центров и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; значений полученных кластерных центров).]]&lt;br /&gt;
[[File:HardCMeans2.PNG|thumb|400px|center|Рисунок 2. Подробное описание работы блока  &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039;. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (1 значение центра кластера на каждую из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; соответствующих вершин графа и значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;), &#039;&#039;&#039;&#039;&#039;d1,...,dC&#039;&#039;&#039;&#039;&#039; — прямое вычисление  расстояния до кластерных центров, &#039;&#039;&#039;&#039;&#039;max&#039;&#039;&#039;&#039;&#039; — вычисление максимума двух чисел (с сохранением соответствующего максимуму кластерного индекса) и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (индекс кластерного центра, расположенного ближе всего к точке &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;, и соответствующее расстояние).]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
Для выполнения одной итерации алгоритма C средних необходимо выполнить параллельно ряд вычислений для каждого из &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; элементов:&lt;br /&gt;
&lt;br /&gt;
# Вычисление &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; расстояний между элементом и кластерными центрами.&lt;br /&gt;
# Выполнение &amp;lt;math&amp;gt;(C - 1)&amp;lt;/math&amp;gt; сравнений для определения минимального.&lt;br /&gt;
# Определение значений соответствующего рассматриваемому элементу &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; столбца матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Эта последовательность операций может быть выполнена для каждого элемента &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; входной выборки независимо и поэтому составляет основной ресурс параллелизма алгоритма.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; &lt;br /&gt;
*&amp;lt;math&amp;gt;\{u_k\}_{k=1}^{N} \subset \mathbb{R}^n&amp;lt;/math&amp;gt; — исходный набор векторов;&lt;br /&gt;
*&amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; — количество кластеров (&amp;lt;math&amp;gt;2 \leqslant C \leqslant N&amp;lt;/math&amp;gt;);&lt;br /&gt;
* &#039;&#039;(опционально)&#039;&#039; &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; — пороговая точность работы алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;nN+1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
*&amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; — рядовая матрица из пространства &amp;lt;math&amp;gt;\mathbb{R}^{C \times N}&amp;lt;/math&amp;gt;.&lt;br /&gt;
*&amp;lt;math&amp;gt;\{c_k\}_{k=1}^{C}&amp;lt;/math&amp;gt; — набор построенных кластерных центров.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;C(N+n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Назначение:&#039;&#039;&#039; кластеризация больших наборов числовых данных.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Достоинства:&#039;&#039;&#039;&lt;br /&gt;
* лёгкость реализации;&lt;br /&gt;
* вычислительная простота.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Недостатки:&#039;&#039;&#039;&lt;br /&gt;
* нет гарантии, что итеративный процесс сойдётся к оптимальному решению;&lt;br /&gt;
* производительность существенно зависит от выбора начальных кластерных центров.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
1)  [https://github.com/artpar/Hard-Clustering-implementation Последовательная реализация на С++ ]&lt;br /&gt;
&lt;br /&gt;
2) [http://projects.jasmeet.me/2013/03/HardCMeans.html Последовательная реализация на MatLab ]&lt;br /&gt;
&lt;br /&gt;
Параллельных реализаций в свободном доступе обнаружено не было.&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Юрий Комаров</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=8059</id>
		<title>Участник:Светлана Лукьяненко/Строгий алгоритм С средних (Hard C-Means, HCM)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=8059"/>
		<updated>2016-10-14T19:38:07Z</updated>

		<summary type="html">&lt;p&gt;Юрий Комаров: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Строгий алгоритм С средних (Hard C-Means,HCM)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;-&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;-&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;nN+1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;C(N+n)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы описания: [[Участник:Светлана_Лукьяненко|Лукьяненко Светлана]], [[Участник:Юрий_Комаров|Комаров Юрий]].&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Строгий алгоритм C средних&#039;&#039;&#039; (&#039;&#039;&#039;&#039;&#039;Hard C-Means&#039;&#039;&#039;&#039;&#039;; &#039;&#039;Jang, Sun and Mizutani, 1997&#039;&#039;) позволяет распределить большие наборы числовых данных по кластерам в многомерном пространстве&amp;lt;ref&amp;gt;Jan Jantzen «Neurofuzzy Modelling». Электронное издание.&amp;lt;/ref&amp;gt;. Алгоритм является управляемым, так как для работы с ним требуется задание одного параметра — числа кластеров, на которое необходимо разделить данные. &lt;br /&gt;
Входными данными для алгоритма являются набор векторов и количество кластеров, также может задаваться пороговое значение величины объектной функции, по достижении которого расчёт прекращается. Выходными данными для алгоритма является рядовая матрица, отображающая принадлежность исходных элементов построенным кластерам, и центры построенных кластеров.&lt;br /&gt;
&lt;br /&gt;
Первым шагом выполнения алгоритма является инициализация центров кластеров случайными значениями. Дальнейшие шаги алгоритма выполняются итеративно до тех пор, пока объектная функция не станет меньше порогового значения или же значение объектной функции не будет минимально отличаться от полученного на предыдущей итерации. На каждой итерации вычислений выполняются следующие действия:&lt;br /&gt;
&lt;br /&gt;
# Расчёт рядовой матрицы, сопоставляющей каждый вектор с ближайшим кластерным центром.&lt;br /&gt;
# Расчёт объектной функции; проверка условий остановки и завершение расчёта в случае их выполнения.&lt;br /&gt;
# Пересчёт кластерных центров.&lt;br /&gt;
&lt;br /&gt;
Так как алгоритм является итеративным и зависит от начальных значений кластерных центров, он может не сходиться к локальному минимуму.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
==== Входные и выходные данные ====&lt;br /&gt;
На вход подаётся набор векторов &amp;lt;math&amp;gt;\{u_k\}_{k=1}^{N}&amp;lt;/math&amp;gt; пространства &amp;lt;math&amp;gt;\mathbb{R}^n&amp;lt;/math&amp;gt; и количество кластеров &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Конечным результатом работы алгоритма являются построенная рядовая матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, содержащая информацию о принадлежности элементов кластерам:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ij} = \begin{cases}&lt;br /&gt;
1, &amp;amp; u_j \in C_i, \\&lt;br /&gt;
0, &amp;amp; \text{otherwise},&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; подразумевается &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый построенный кластер, и набор &amp;lt;math&amp;gt;\{c_i\}_{i=1}^{C}&amp;lt;/math&amp;gt; центров этих кластеров.&lt;br /&gt;
&lt;br /&gt;
==== Описание алгоритма ====&lt;br /&gt;
Алгоритм состоит из 5 последовательных шагов.&amp;lt;ref&amp;gt; Нейский И.М. Классификация и сравнение методов кластеризации.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 1&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация кластерных центров&#039;&#039;&#039; &amp;lt;math&amp;gt;c_i \, (i=1,2,\ldots,C)&amp;lt;/math&amp;gt; может происходить за счёт случайного выбора необходимого числа точек из входного набора либо путём явного указания.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 2&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вычисление рядовой матрицы&#039;&#039;&#039; &amp;lt;math&amp;gt;M = \|m_{ik}\|&amp;lt;/math&amp;gt;, элементы которой задаются следующими выражениями (&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; — количество элементов во входном наборе данных):&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ik} = \begin{cases}&lt;br /&gt;
1, &amp;amp; \|u_k-c_i\|^2 \leqslant \|u_k-c_j\|^2 \;\; \text{for all } i \neq j; \;\; (i,j=1,2,\ldots,C; \; k = 1,2,\ldots,N)\\&lt;br /&gt;
0, &amp;amp; \text{otherwise}.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;!-- При этом, как легко видеть, матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; обладает следующими свойствами:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\sum\limits_{i=1}^C m_{ij} = 1, \;\; \sum\limits_{i=1}^C\sum\limits_{j=1}^K m_{ij} = K.&lt;br /&gt;
&amp;lt;/math&amp;gt; --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Будем говорить, что &amp;lt;math&amp;gt;u_k \in C_i&amp;lt;/math&amp;gt;, если &amp;lt;math&amp;gt;m_{ik} = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 3&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Расчёт объектной функции:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^C J_i = \sum\limits_{i=1}^C \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right)&lt;br /&gt;
.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На этом шаге происходит &#039;&#039;&#039;&amp;lt;u&amp;gt;остановка и выход из цикла&amp;lt;/u&amp;gt;&#039;&#039;&#039;, если полученное значение ниже пороговой величины &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; или полученное значение не сильно отличается от значений, полученных на предыдущих циклах.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 4&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Пересчёт кластерных центров&#039;&#039;&#039; выполняется в соответствии со следующим уравнением:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;|C_i|&amp;lt;/math&amp;gt; подразумевается количество элементов в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом кластере.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 5&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Переход по циклу&#039;&#039;&#039; на шаг 2.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма составляют вычисления квадратов нормы расстояния от каждого из векторов исходной выборки до промежуточных кластерных центров &amp;lt;math&amp;gt;\|u_k-c_i\|^2&amp;lt;/math&amp;gt;. На каждой итерации алгоритма происходит расчёт &amp;lt;math&amp;gt;CN&amp;lt;/math&amp;gt; таких расстояний.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Основной операцией, выполняемой в алгоритме, как сказано выше, является операция нахождения квадратов расстояний между векторами данных и кластерными центрами. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
d_{ki} = \|u_k-c_i\|^2&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также на шаге вычисления объектной функции производится множественное суммирование полученных расстояний:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^C J_i = \sum\limits_{i=1}^C \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right),&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
а на шаге расчета кластерных центров происходит суммирование векторов:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Реализация последовательного алгоритма состоит в итеративном повторении блока, описанного далее в форме псевдокода, до тех пор, пока не будет достигнута желаемая точность.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;&lt;br /&gt;
J = 0;&lt;br /&gt;
M = zeros(N,C);&lt;br /&gt;
for i = 1 to N //go through every element&lt;br /&gt;
   d_min = MAXINT;&lt;br /&gt;
   j_min = 1;&lt;br /&gt;
   for j = 1 to C //deside which claster does element belong to&lt;br /&gt;
      d_ij  = sq_norm(u[i] - c[j]);&lt;br /&gt;
      if d_ij &amp;lt; d_min&lt;br /&gt;
         d_min = d_ij;&lt;br /&gt;
         j_min = j;&lt;br /&gt;
   //generation of output data&lt;br /&gt;
   J += d_min; &lt;br /&gt;
   M[i,j_min] = 1;&lt;br /&gt;
   c_new[j] += u[i];&lt;br /&gt;
   c_newCount[k]++;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
На каждой итерации алгоритма требуется выполнение:&lt;br /&gt;
* &amp;lt;math&amp;gt;NC&amp;lt;/math&amp;gt; операций вычисления квадрата нормы разности элементов;&lt;br /&gt;
* &amp;lt;math&amp;gt;NC&amp;lt;/math&amp;gt; операций сравнения (вычитаний);&lt;br /&gt;
* &amp;lt;math&amp;gt;3N&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
&lt;br /&gt;
Каждая операция вычисления нормы разности векторов предполагает выполнение &amp;lt;math&amp;gt;2n-1&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания и &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; операций возведения в квадрат (умножений), поэтому получаем для каждой итерации:&lt;br /&gt;
* &amp;lt;math&amp;gt;(2n-1)NC&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания;&lt;br /&gt;
* &amp;lt;math&amp;gt;(3+(n+1)C)N&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
&lt;br /&gt;
Ожидая, что предельная точность будет достигнута менее, чем за &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; итераций (в противном случае применение алгоритма можно считать нецелесообразным), получаем итоговую сложность последовательной реализации алгоритма &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt; (в предположении, что &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; существенно меньше &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
[[File:HardCMeans1.png|thumb|800px|center|Рисунок 1. Информационный граф алгоритма. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (&amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; стартовых значений кластерных центров и 1 значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; на каждую вершину графа), &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039; — вычисление минимального расстояния до кластерных центров (подробнее см. рисунок 2), &#039;&#039;&#039;&#039;&#039;M&#039;&#039;&#039;&#039;&#039; — запись единички в соответствующую строчку матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, &#039;&#039;&#039;&#039;&#039;J&#039;&#039;&#039;&#039;&#039; — вычисление объектной функции по результатам полученных вычислений, &#039;&#039;&#039;&#039;&#039;if&#039;&#039;&#039;&#039;&#039; — проверка условия достижения заданной точности, &#039;&#039;&#039;&#039;&#039;{c}&#039;&#039;&#039;&#039;&#039; — пересчёт кластерных центров и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; значений полученных кластерных центров).]]&lt;br /&gt;
[[File:HardCMeans2.PNG|thumb|400px|center|Рисунок 2. Подробное описание работы блока  &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039;. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (1 значение центра кластера на каждую из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; соответствующих вершин графа и значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;), &#039;&#039;&#039;&#039;&#039;d1,...,dC&#039;&#039;&#039;&#039;&#039; — прямое вычисление  расстояния до кластерных центров, &#039;&#039;&#039;&#039;&#039;max&#039;&#039;&#039;&#039;&#039; — вычисление максимума двух чисел (с сохранением соответствующего максимуму кластерного индекса) и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (индекс кластерного центра, расположенного ближе всего к точке &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;, и соответствующее расстояние).]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
Для выполнения одной итерации алгоритма C средних необходимо выполнить параллельно ряд вычислений для каждого из &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; элементов:&lt;br /&gt;
&lt;br /&gt;
# Вычисление &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; расстояний между элементом и кластерными центрами.&lt;br /&gt;
# Выполнение &amp;lt;math&amp;gt;(C - 1)&amp;lt;/math&amp;gt; сравнений для определения минимального.&lt;br /&gt;
# Определение значений соответствующего рассматриваемому элементу &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; столбца матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Эта последовательность операций может быть выполнена для каждого элемента &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; входной выборки независимо и поэтому составляет основной ресурс параллелизма алгоритма.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; &lt;br /&gt;
*&amp;lt;math&amp;gt;\{u_k\}_{k=1}^{N} \subset \mathbb{R}^n&amp;lt;/math&amp;gt; — исходный набор векторов;&lt;br /&gt;
*&amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; — количество кластеров (&amp;lt;math&amp;gt;2 \leqslant C \leqslant N&amp;lt;/math&amp;gt;);&lt;br /&gt;
* &#039;&#039;(опционально)&#039;&#039; &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; — пороговая точность работы алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;nN+1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
*&amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; — рядовая матрица из пространства &amp;lt;math&amp;gt;\mathbb{R}^{C \times N}&amp;lt;/math&amp;gt;.&lt;br /&gt;
*&amp;lt;math&amp;gt;\{c_k\}_{k=1}^{C}&amp;lt;/math&amp;gt; — набор построенных кластерных центров.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;C(N+n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Назначение:&#039;&#039;&#039; кластеризация больших наборов числовых данных.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Достоинства:&#039;&#039;&#039;&lt;br /&gt;
* лёгкость реализации;&lt;br /&gt;
* вычислительная простота.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Недостатки:&#039;&#039;&#039;&lt;br /&gt;
* нет гарантии, что итеративный процесс сойдётся к оптимальному решению;&lt;br /&gt;
* производительность существенно зависит от выбора начальных кластерных центров.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
1)  [https://github.com/artpar/Hard-Clustering-implementation Последовательная реализация на С++ ]&lt;br /&gt;
&lt;br /&gt;
2) [http://projects.jasmeet.me/2013/03/HardCMeans.html Последовательная реализация на MatLab ]&lt;br /&gt;
&lt;br /&gt;
Параллельных реализаций в свободном доступе обнаружено не было.&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Юрий Комаров</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=8055</id>
		<title>Участник:Светлана Лукьяненко/Строгий алгоритм С средних (Hard C-Means, HCM)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=8055"/>
		<updated>2016-10-14T19:35:07Z</updated>

		<summary type="html">&lt;p&gt;Юрий Комаров: /* Входные и выходные данные алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Строгий алгоритм С средних (Hard C-Means,HCM)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;-&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;-&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mn+1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;cn&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы описания: [[Участник:Светлана_Лукьяненко|Лукьяненко Светлана]], [[Участник:Юрий_Комаров|Комаров Юрий]].&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Строгий алгоритм C средних&#039;&#039;&#039; (&#039;&#039;&#039;&#039;&#039;Hard C-Means&#039;&#039;&#039;&#039;&#039;; &#039;&#039;Jang, Sun and Mizutani, 1997&#039;&#039;) позволяет распределить большие наборы числовых данных по кластерам в многомерном пространстве&amp;lt;ref&amp;gt;Jan Jantzen «Neurofuzzy Modelling». Электронное издание.&amp;lt;/ref&amp;gt;. Алгоритм является управляемым, так как для работы с ним требуется задание одного параметра — числа кластеров, на которое необходимо разделить данные. &lt;br /&gt;
Входными данными для алгоритма являются набор векторов и количество кластеров, также может задаваться пороговое значение величины объектной функции, по достижении которого расчёт прекращается. Выходными данными для алгоритма является рядовая матрица, отображающая принадлежность исходных элементов построенным кластерам, и центры построенных кластеров.&lt;br /&gt;
&lt;br /&gt;
Первым шагом выполнения алгоритма является инициализация центров кластеров случайными значениями. Дальнейшие шаги алгоритма выполняются итеративно до тех пор, пока объектная функция не станет меньше порогового значения или же значение объектной функции не будет минимально отличаться от полученного на предыдущей итерации. На каждой итерации вычислений выполняются следующие действия:&lt;br /&gt;
&lt;br /&gt;
# Расчёт рядовой матрицы, сопоставляющей каждый вектор с ближайшим кластерным центром.&lt;br /&gt;
# Расчёт объектной функции; проверка условий остановки и завершение расчёта в случае их выполнения.&lt;br /&gt;
# Пересчёт кластерных центров.&lt;br /&gt;
&lt;br /&gt;
Так как алгоритм является итеративным и зависит от начальных значений кластерных центров, он может не сходиться к локальному минимуму.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
==== Входные и выходные данные ====&lt;br /&gt;
На вход подаётся набор векторов &amp;lt;math&amp;gt;\{u_k\}_{k=1}^{N}&amp;lt;/math&amp;gt; пространства &amp;lt;math&amp;gt;\mathbb{R}^n&amp;lt;/math&amp;gt; и количество кластеров &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Конечным результатом работы алгоритма являются построенная рядовая матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, содержащая информацию о принадлежности элементов кластерам:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ij} = \begin{cases}&lt;br /&gt;
1, &amp;amp; u_j \in C_i, \\&lt;br /&gt;
0, &amp;amp; \text{otherwise},&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; подразумевается &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый построенный кластер, и набор &amp;lt;math&amp;gt;\{c_i\}_{i=1}^{C}&amp;lt;/math&amp;gt; центров этих кластеров.&lt;br /&gt;
&lt;br /&gt;
==== Описание алгоритма ====&lt;br /&gt;
Алгоритм состоит из 5 последовательных шагов.&amp;lt;ref&amp;gt; Нейский И.М. Классификация и сравнение методов кластеризации.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 1&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация кластерных центров&#039;&#039;&#039; &amp;lt;math&amp;gt;c_i \, (i=1,2,\ldots,C)&amp;lt;/math&amp;gt; может происходить за счёт случайного выбора необходимого числа точек из входного набора либо путём явного указания.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 2&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вычисление рядовой матрицы&#039;&#039;&#039; &amp;lt;math&amp;gt;M = \|m_{ik}\|&amp;lt;/math&amp;gt;, элементы которой задаются следующими выражениями (&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; — количество элементов во входном наборе данных):&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ik} = \begin{cases}&lt;br /&gt;
1, &amp;amp; \|u_k-c_i\|^2 \leqslant \|u_k-c_j\|^2 \;\; \text{for all } i \neq j; \;\; (i,j=1,2,\ldots,C; \; k = 1,2,\ldots,N)\\&lt;br /&gt;
0, &amp;amp; \text{otherwise}.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;!-- При этом, как легко видеть, матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; обладает следующими свойствами:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\sum\limits_{i=1}^C m_{ij} = 1, \;\; \sum\limits_{i=1}^C\sum\limits_{j=1}^K m_{ij} = K.&lt;br /&gt;
&amp;lt;/math&amp;gt; --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Будем говорить, что &amp;lt;math&amp;gt;u_k \in C_i&amp;lt;/math&amp;gt;, если &amp;lt;math&amp;gt;m_{ik} = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 3&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Расчёт объектной функции:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^C J_i = \sum\limits_{i=1}^C \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right)&lt;br /&gt;
.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На этом шаге происходит &#039;&#039;&#039;&amp;lt;u&amp;gt;остановка и выход из цикла&amp;lt;/u&amp;gt;&#039;&#039;&#039;, если полученное значение ниже пороговой величины &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; или полученное значение не сильно отличается от значений, полученных на предыдущих циклах.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 4&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Пересчёт кластерных центров&#039;&#039;&#039; выполняется в соответствии со следующим уравнением:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;|C_i|&amp;lt;/math&amp;gt; подразумевается количество элементов в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом кластере.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 5&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Переход по циклу&#039;&#039;&#039; на шаг 2.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма составляют вычисления квадратов нормы расстояния от каждого из векторов исходной выборки до промежуточных кластерных центров &amp;lt;math&amp;gt;\|u_k-c_i\|^2&amp;lt;/math&amp;gt;. На каждой итерации алгоритма происходит расчёт &amp;lt;math&amp;gt;CN&amp;lt;/math&amp;gt; таких расстояний.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Основной операцией, выполняемой в алгоритме, как сказано выше, является операция нахождения квадратов расстояний между векторами данных и кластерными центрами. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
d_{ki} = \|u_k-c_i\|^2&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также на шаге вычисления объектной функции производится множественное суммирование полученных расстояний:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^C J_i = \sum\limits_{i=1}^C \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right),&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
а на шаге расчета кластерных центров происходит суммирование векторов:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Реализация последовательного алгоритма состоит в итеративном повторении блока, описанного далее в форме псевдокода, до тех пор, пока не будет достигнута желаемая точность.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;&lt;br /&gt;
J = 0;&lt;br /&gt;
M = zeros(N,C);&lt;br /&gt;
for i = 1 to N //go through every element&lt;br /&gt;
   d_min = MAXINT;&lt;br /&gt;
   j_min = 1;&lt;br /&gt;
   for j = 1 to C //deside which claster does element belong to&lt;br /&gt;
      d_ij  = sq_norm(u[i] - c[j]);&lt;br /&gt;
      if d_ij &amp;lt; d_min&lt;br /&gt;
         d_min = d_ij;&lt;br /&gt;
         j_min = j;&lt;br /&gt;
   //generation of output data&lt;br /&gt;
   J += d_min; &lt;br /&gt;
   M[i,j_min] = 1;&lt;br /&gt;
   c_new[j] += u[i];&lt;br /&gt;
   c_newCount[k]++;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
На каждой итерации алгоритма требуется выполнение:&lt;br /&gt;
* &amp;lt;math&amp;gt;NC&amp;lt;/math&amp;gt; операций вычисления квадрата нормы разности элементов;&lt;br /&gt;
* &amp;lt;math&amp;gt;NC&amp;lt;/math&amp;gt; операций сравнения (вычитаний);&lt;br /&gt;
* &amp;lt;math&amp;gt;3N&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
&lt;br /&gt;
Каждая операция вычисления нормы разности векторов предполагает выполнение &amp;lt;math&amp;gt;2n-1&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания и &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; операций возведения в квадрат (умножений), поэтому получаем для каждой итерации:&lt;br /&gt;
* &amp;lt;math&amp;gt;(2n-1)NC&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания;&lt;br /&gt;
* &amp;lt;math&amp;gt;(3+(n+1)C)N&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
&lt;br /&gt;
Ожидая, что предельная точность будет достигнута менее, чем за &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; итераций (в противном случае применение алгоритма можно считать нецелесообразным), получаем итоговую сложность последовательной реализации алгоритма &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt; (в предположении, что &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; существенно меньше &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
[[File:HardCMeans1.png|thumb|800px|center|Рисунок 1. Информационный граф алгоритма. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (&amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; стартовых значений кластерных центров и 1 значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; на каждую вершину графа), &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039; — вычисление минимального расстояния до кластерных центров (подробнее см. рисунок 2), &#039;&#039;&#039;&#039;&#039;M&#039;&#039;&#039;&#039;&#039; — запись единички в соответствующую строчку матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, &#039;&#039;&#039;&#039;&#039;J&#039;&#039;&#039;&#039;&#039; — вычисление объектной функции по результатам полученных вычислений, &#039;&#039;&#039;&#039;&#039;if&#039;&#039;&#039;&#039;&#039; — проверка условия достижения заданной точности, &#039;&#039;&#039;&#039;&#039;{c}&#039;&#039;&#039;&#039;&#039; — пересчёт кластерных центров и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; значений полученных кластерных центров).]]&lt;br /&gt;
[[File:HardCMeans2.PNG|thumb|400px|center|Рисунок 2. Подробное описание работы блока  &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039;. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (1 значение центра кластера на каждую из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; соответствующих вершин графа и значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;), &#039;&#039;&#039;&#039;&#039;d1,...,dC&#039;&#039;&#039;&#039;&#039; — прямое вычисление  расстояния до кластерных центров, &#039;&#039;&#039;&#039;&#039;max&#039;&#039;&#039;&#039;&#039; — вычисление максимума двух чисел (с сохранением соответствующего максимуму кластерного индекса) и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (индекс кластерного центра, расположенного ближе всего к точке &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;, и соответствующее расстояние).]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
Для выполнения одной итерации алгоритма C средних необходимо выполнить параллельно ряд вычислений для каждого из &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; элементов:&lt;br /&gt;
&lt;br /&gt;
# Вычисление &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; расстояний между элементом и кластерными центрами.&lt;br /&gt;
# Выполнение &amp;lt;math&amp;gt;(C - 1)&amp;lt;/math&amp;gt; сравнений для определения минимального.&lt;br /&gt;
# Определение значений соответствующего рассматриваемому элементу &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; столбца матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Эта последовательность операций может быть выполнена для каждого элемента &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; входной выборки независимо и поэтому составляет основной ресурс параллелизма алгоритма.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; &lt;br /&gt;
*&amp;lt;math&amp;gt;\{u_k\}_{k=1}^{N} \subset \mathbb{R}^n&amp;lt;/math&amp;gt; — исходный набор векторов;&lt;br /&gt;
*&amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; — количество кластеров (&amp;lt;math&amp;gt;2 \leqslant C \leqslant N&amp;lt;/math&amp;gt;);&lt;br /&gt;
* &#039;&#039;(опционально)&#039;&#039; &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; — пороговая точность работы алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;nN+1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
*&amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; — рядовая матрица из пространства &amp;lt;math&amp;gt;\mathbb{R}^{C \times N}&amp;lt;/math&amp;gt;.&lt;br /&gt;
*&amp;lt;math&amp;gt;\{c_k\}_{k=1}^{C}&amp;lt;/math&amp;gt; — набор построенных кластерных центров.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;C(N+n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Назначение:&#039;&#039;&#039; кластеризация больших наборов числовых данных.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Достоинства:&#039;&#039;&#039;&lt;br /&gt;
* лёгкость реализации;&lt;br /&gt;
* вычислительная простота.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Недостатки:&#039;&#039;&#039;&lt;br /&gt;
* нет гарантии, что итеративный процесс сойдётся к оптимальному решению;&lt;br /&gt;
* производительность существенно зависит от выбора начальных кластерных центров.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
1)  [https://github.com/artpar/Hard-Clustering-implementation Последовательная реализация на С++ ]&lt;br /&gt;
&lt;br /&gt;
2) [http://projects.jasmeet.me/2013/03/HardCMeans.html Последовательная реализация на MatLab ]&lt;br /&gt;
&lt;br /&gt;
Параллельных реализаций в свободном доступе обнаружено не было.&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Юрий Комаров</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=8049</id>
		<title>Участник:Светлана Лукьяненко/Строгий алгоритм С средних (Hard C-Means, HCM)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=8049"/>
		<updated>2016-10-14T19:32:34Z</updated>

		<summary type="html">&lt;p&gt;Юрий Комаров: /* Ресурс параллелизма алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Строгий алгоритм С средних (Hard C-Means,HCM)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;-&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;-&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mn+1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;cn&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы описания: [[Участник:Светлана_Лукьяненко|Лукьяненко Светлана]], [[Участник:Юрий_Комаров|Комаров Юрий]].&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Строгий алгоритм C средних&#039;&#039;&#039; (&#039;&#039;&#039;&#039;&#039;Hard C-Means&#039;&#039;&#039;&#039;&#039;; &#039;&#039;Jang, Sun and Mizutani, 1997&#039;&#039;) позволяет распределить большие наборы числовых данных по кластерам в многомерном пространстве&amp;lt;ref&amp;gt;Jan Jantzen «Neurofuzzy Modelling». Электронное издание.&amp;lt;/ref&amp;gt;. Алгоритм является управляемым, так как для работы с ним требуется задание одного параметра — числа кластеров, на которое необходимо разделить данные. &lt;br /&gt;
Входными данными для алгоритма являются набор векторов и количество кластеров, также может задаваться пороговое значение величины объектной функции, по достижении которого расчёт прекращается. Выходными данными для алгоритма является рядовая матрица, отображающая принадлежность исходных элементов построенным кластерам, и центры построенных кластеров.&lt;br /&gt;
&lt;br /&gt;
Первым шагом выполнения алгоритма является инициализация центров кластеров случайными значениями. Дальнейшие шаги алгоритма выполняются итеративно до тех пор, пока объектная функция не станет меньше порогового значения или же значение объектной функции не будет минимально отличаться от полученного на предыдущей итерации. На каждой итерации вычислений выполняются следующие действия:&lt;br /&gt;
&lt;br /&gt;
# Расчёт рядовой матрицы, сопоставляющей каждый вектор с ближайшим кластерным центром.&lt;br /&gt;
# Расчёт объектной функции; проверка условий остановки и завершение расчёта в случае их выполнения.&lt;br /&gt;
# Пересчёт кластерных центров.&lt;br /&gt;
&lt;br /&gt;
Так как алгоритм является итеративным и зависит от начальных значений кластерных центров, он может не сходиться к локальному минимуму.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
==== Входные и выходные данные ====&lt;br /&gt;
На вход подаётся набор векторов &amp;lt;math&amp;gt;\{u_k\}_{k=1}^{N}&amp;lt;/math&amp;gt; пространства &amp;lt;math&amp;gt;\mathbb{R}^n&amp;lt;/math&amp;gt; и количество кластеров &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Конечным результатом работы алгоритма являются построенная рядовая матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, содержащая информацию о принадлежности элементов кластерам:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ij} = \begin{cases}&lt;br /&gt;
1, &amp;amp; u_j \in C_i, \\&lt;br /&gt;
0, &amp;amp; \text{otherwise},&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; подразумевается &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый построенный кластер, и набор &amp;lt;math&amp;gt;\{c_i\}_{i=1}^{C}&amp;lt;/math&amp;gt; центров этих кластеров.&lt;br /&gt;
&lt;br /&gt;
==== Описание алгоритма ====&lt;br /&gt;
Алгоритм состоит из 5 последовательных шагов.&amp;lt;ref&amp;gt; Нейский И.М. Классификация и сравнение методов кластеризации.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 1&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация кластерных центров&#039;&#039;&#039; &amp;lt;math&amp;gt;c_i \, (i=1,2,\ldots,C)&amp;lt;/math&amp;gt; может происходить за счёт случайного выбора необходимого числа точек из входного набора либо путём явного указания.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 2&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вычисление рядовой матрицы&#039;&#039;&#039; &amp;lt;math&amp;gt;M = \|m_{ik}\|&amp;lt;/math&amp;gt;, элементы которой задаются следующими выражениями (&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; — количество элементов во входном наборе данных):&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ik} = \begin{cases}&lt;br /&gt;
1, &amp;amp; \|u_k-c_i\|^2 \leqslant \|u_k-c_j\|^2 \;\; \text{for all } i \neq j; \;\; (i,j=1,2,\ldots,C; \; k = 1,2,\ldots,N)\\&lt;br /&gt;
0, &amp;amp; \text{otherwise}.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;!-- При этом, как легко видеть, матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; обладает следующими свойствами:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\sum\limits_{i=1}^C m_{ij} = 1, \;\; \sum\limits_{i=1}^C\sum\limits_{j=1}^K m_{ij} = K.&lt;br /&gt;
&amp;lt;/math&amp;gt; --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Будем говорить, что &amp;lt;math&amp;gt;u_k \in C_i&amp;lt;/math&amp;gt;, если &amp;lt;math&amp;gt;m_{ik} = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 3&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Расчёт объектной функции:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^C J_i = \sum\limits_{i=1}^C \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right)&lt;br /&gt;
.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На этом шаге происходит &#039;&#039;&#039;&amp;lt;u&amp;gt;остановка и выход из цикла&amp;lt;/u&amp;gt;&#039;&#039;&#039;, если полученное значение ниже пороговой величины &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; или полученное значение не сильно отличается от значений, полученных на предыдущих циклах.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 4&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Пересчёт кластерных центров&#039;&#039;&#039; выполняется в соответствии со следующим уравнением:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;|C_i|&amp;lt;/math&amp;gt; подразумевается количество элементов в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом кластере.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 5&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Переход по циклу&#039;&#039;&#039; на шаг 2.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма составляют вычисления квадратов нормы расстояния от каждого из векторов исходной выборки до промежуточных кластерных центров &amp;lt;math&amp;gt;\|u_k-c_i\|^2&amp;lt;/math&amp;gt;. На каждой итерации алгоритма происходит расчёт &amp;lt;math&amp;gt;CN&amp;lt;/math&amp;gt; таких расстояний.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Основной операцией, выполняемой в алгоритме, как сказано выше, является операция нахождения квадратов расстояний между векторами данных и кластерными центрами. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
d_{ki} = \|u_k-c_i\|^2&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также на шаге вычисления объектной функции производится множественное суммирование полученных расстояний:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^C J_i = \sum\limits_{i=1}^C \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right),&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
а на шаге расчета кластерных центров происходит суммирование векторов:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Реализация последовательного алгоритма состоит в итеративном повторении блока, описанного далее в форме псевдокода, до тех пор, пока не будет достигнута желаемая точность.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;&lt;br /&gt;
J = 0;&lt;br /&gt;
M = zeros(N,C);&lt;br /&gt;
for i = 1 to N //go through every element&lt;br /&gt;
   d_min = MAXINT;&lt;br /&gt;
   j_min = 1;&lt;br /&gt;
   for j = 1 to C //deside which claster does element belong to&lt;br /&gt;
      d_ij  = sq_norm(u[i] - c[j]);&lt;br /&gt;
      if d_ij &amp;lt; d_min&lt;br /&gt;
         d_min = d_ij;&lt;br /&gt;
         j_min = j;&lt;br /&gt;
   //generation of output data&lt;br /&gt;
   J += d_min; &lt;br /&gt;
   M[i,j_min] = 1;&lt;br /&gt;
   c_new[j] += u[i];&lt;br /&gt;
   c_newCount[k]++;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
На каждой итерации алгоритма требуется выполнение:&lt;br /&gt;
* &amp;lt;math&amp;gt;NC&amp;lt;/math&amp;gt; операций вычисления квадрата нормы разности элементов;&lt;br /&gt;
* &amp;lt;math&amp;gt;NC&amp;lt;/math&amp;gt; операций сравнения (вычитаний);&lt;br /&gt;
* &amp;lt;math&amp;gt;3N&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
&lt;br /&gt;
Каждая операция вычисления нормы разности векторов предполагает выполнение &amp;lt;math&amp;gt;2n-1&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания и &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; операций возведения в квадрат (умножений), поэтому получаем для каждой итерации:&lt;br /&gt;
* &amp;lt;math&amp;gt;(2n-1)NC&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания;&lt;br /&gt;
* &amp;lt;math&amp;gt;(3+(n+1)C)N&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
&lt;br /&gt;
Ожидая, что предельная точность будет достигнута менее, чем за &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; итераций (в противном случае применение алгоритма можно считать нецелесообразным), получаем итоговую сложность последовательной реализации алгоритма &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt; (в предположении, что &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; существенно меньше &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
[[File:HardCMeans1.png|thumb|800px|center|Рисунок 1. Информационный граф алгоритма. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (&amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; стартовых значений кластерных центров и 1 значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; на каждую вершину графа), &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039; — вычисление минимального расстояния до кластерных центров (подробнее см. рисунок 2), &#039;&#039;&#039;&#039;&#039;M&#039;&#039;&#039;&#039;&#039; — запись единички в соответствующую строчку матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, &#039;&#039;&#039;&#039;&#039;J&#039;&#039;&#039;&#039;&#039; — вычисление объектной функции по результатам полученных вычислений, &#039;&#039;&#039;&#039;&#039;if&#039;&#039;&#039;&#039;&#039; — проверка условия достижения заданной точности, &#039;&#039;&#039;&#039;&#039;{c}&#039;&#039;&#039;&#039;&#039; — пересчёт кластерных центров и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; значений полученных кластерных центров).]]&lt;br /&gt;
[[File:HardCMeans2.PNG|thumb|400px|center|Рисунок 2. Подробное описание работы блока  &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039;. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (1 значение центра кластера на каждую из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; соответствующих вершин графа и значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;), &#039;&#039;&#039;&#039;&#039;d1,...,dC&#039;&#039;&#039;&#039;&#039; — прямое вычисление  расстояния до кластерных центров, &#039;&#039;&#039;&#039;&#039;max&#039;&#039;&#039;&#039;&#039; — вычисление максимума двух чисел (с сохранением соответствующего максимуму кластерного индекса) и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (индекс кластерного центра, расположенного ближе всего к точке &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;, и соответствующее расстояние).]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
Для выполнения одной итерации алгоритма C средних необходимо выполнить параллельно ряд вычислений для каждого из &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; элементов:&lt;br /&gt;
&lt;br /&gt;
# Вычисление &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; расстояний между элементом и кластерными центрами.&lt;br /&gt;
# Выполнение &amp;lt;math&amp;gt;(C - 1)&amp;lt;/math&amp;gt; сравнений для определения минимального.&lt;br /&gt;
# Определение значений соответствующего рассматриваемому элементу &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; столбца матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Эта последовательность операций может быть выполнена для каждого элемента &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; входной выборки независимо и поэтому составляет основной ресурс параллелизма алгоритма.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; &lt;br /&gt;
*&amp;lt;math&amp;gt;\{u_k\}_{k=1}^{n} \subset \mathbb{R}^m&amp;lt;/math&amp;gt; — исходный набор векторов;&lt;br /&gt;
*&amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; — желаемое количество кластеров (&amp;lt;math&amp;gt;2 \leqslant c \leqslant n&amp;lt;/math&amp;gt;);&lt;br /&gt;
* &#039;&#039;(опционально)&#039;&#039; &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; — пороговая точность работы алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;mn+1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
*&amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; — рядовая матрица из пространства &amp;lt;math&amp;gt;\mathbb{R}^{c \times n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;cn&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Назначение:&#039;&#039;&#039; кластеризация больших наборов числовых данных.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Достоинства:&#039;&#039;&#039;&lt;br /&gt;
* лёгкость реализации;&lt;br /&gt;
* вычислительная простота.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Недостатки:&#039;&#039;&#039;&lt;br /&gt;
* нет гарантии, что итеративный процесс сойдётся к оптимальному решению;&lt;br /&gt;
* производительность существенно зависит от выбора начальных кластерных центров.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
1)  [https://github.com/artpar/Hard-Clustering-implementation Последовательная реализация на С++ ]&lt;br /&gt;
&lt;br /&gt;
2) [http://projects.jasmeet.me/2013/03/HardCMeans.html Последовательная реализация на MatLab ]&lt;br /&gt;
&lt;br /&gt;
Параллельных реализаций в свободном доступе обнаружено не было.&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Юрий Комаров</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=8043</id>
		<title>Участник:Светлана Лукьяненко/Строгий алгоритм С средних (Hard C-Means, HCM)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=8043"/>
		<updated>2016-10-14T19:29:24Z</updated>

		<summary type="html">&lt;p&gt;Юрий Комаров: /* Описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Строгий алгоритм С средних (Hard C-Means,HCM)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;-&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;-&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mn+1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;cn&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы описания: [[Участник:Светлана_Лукьяненко|Лукьяненко Светлана]], [[Участник:Юрий_Комаров|Комаров Юрий]].&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Строгий алгоритм C средних&#039;&#039;&#039; (&#039;&#039;&#039;&#039;&#039;Hard C-Means&#039;&#039;&#039;&#039;&#039;; &#039;&#039;Jang, Sun and Mizutani, 1997&#039;&#039;) позволяет распределить большие наборы числовых данных по кластерам в многомерном пространстве&amp;lt;ref&amp;gt;Jan Jantzen «Neurofuzzy Modelling». Электронное издание.&amp;lt;/ref&amp;gt;. Алгоритм является управляемым, так как для работы с ним требуется задание одного параметра — числа кластеров, на которое необходимо разделить данные. &lt;br /&gt;
Входными данными для алгоритма являются набор векторов и количество кластеров, также может задаваться пороговое значение величины объектной функции, по достижении которого расчёт прекращается. Выходными данными для алгоритма является рядовая матрица, отображающая принадлежность исходных элементов построенным кластерам, и центры построенных кластеров.&lt;br /&gt;
&lt;br /&gt;
Первым шагом выполнения алгоритма является инициализация центров кластеров случайными значениями. Дальнейшие шаги алгоритма выполняются итеративно до тех пор, пока объектная функция не станет меньше порогового значения или же значение объектной функции не будет минимально отличаться от полученного на предыдущей итерации. На каждой итерации вычислений выполняются следующие действия:&lt;br /&gt;
&lt;br /&gt;
# Расчёт рядовой матрицы, сопоставляющей каждый вектор с ближайшим кластерным центром.&lt;br /&gt;
# Расчёт объектной функции; проверка условий остановки и завершение расчёта в случае их выполнения.&lt;br /&gt;
# Пересчёт кластерных центров.&lt;br /&gt;
&lt;br /&gt;
Так как алгоритм является итеративным и зависит от начальных значений кластерных центров, он может не сходиться к локальному минимуму.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
==== Входные и выходные данные ====&lt;br /&gt;
На вход подаётся набор векторов &amp;lt;math&amp;gt;\{u_k\}_{k=1}^{N}&amp;lt;/math&amp;gt; пространства &amp;lt;math&amp;gt;\mathbb{R}^n&amp;lt;/math&amp;gt; и количество кластеров &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Конечным результатом работы алгоритма являются построенная рядовая матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, содержащая информацию о принадлежности элементов кластерам:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ij} = \begin{cases}&lt;br /&gt;
1, &amp;amp; u_j \in C_i, \\&lt;br /&gt;
0, &amp;amp; \text{otherwise},&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; подразумевается &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый построенный кластер, и набор &amp;lt;math&amp;gt;\{c_i\}_{i=1}^{C}&amp;lt;/math&amp;gt; центров этих кластеров.&lt;br /&gt;
&lt;br /&gt;
==== Описание алгоритма ====&lt;br /&gt;
Алгоритм состоит из 5 последовательных шагов.&amp;lt;ref&amp;gt; Нейский И.М. Классификация и сравнение методов кластеризации.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 1&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация кластерных центров&#039;&#039;&#039; &amp;lt;math&amp;gt;c_i \, (i=1,2,\ldots,C)&amp;lt;/math&amp;gt; может происходить за счёт случайного выбора необходимого числа точек из входного набора либо путём явного указания.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 2&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вычисление рядовой матрицы&#039;&#039;&#039; &amp;lt;math&amp;gt;M = \|m_{ik}\|&amp;lt;/math&amp;gt;, элементы которой задаются следующими выражениями (&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; — количество элементов во входном наборе данных):&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ik} = \begin{cases}&lt;br /&gt;
1, &amp;amp; \|u_k-c_i\|^2 \leqslant \|u_k-c_j\|^2 \;\; \text{for all } i \neq j; \;\; (i,j=1,2,\ldots,C; \; k = 1,2,\ldots,N)\\&lt;br /&gt;
0, &amp;amp; \text{otherwise}.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;!-- При этом, как легко видеть, матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; обладает следующими свойствами:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\sum\limits_{i=1}^C m_{ij} = 1, \;\; \sum\limits_{i=1}^C\sum\limits_{j=1}^K m_{ij} = K.&lt;br /&gt;
&amp;lt;/math&amp;gt; --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Будем говорить, что &amp;lt;math&amp;gt;u_k \in C_i&amp;lt;/math&amp;gt;, если &amp;lt;math&amp;gt;m_{ik} = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 3&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Расчёт объектной функции:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^C J_i = \sum\limits_{i=1}^C \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right)&lt;br /&gt;
.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На этом шаге происходит &#039;&#039;&#039;&amp;lt;u&amp;gt;остановка и выход из цикла&amp;lt;/u&amp;gt;&#039;&#039;&#039;, если полученное значение ниже пороговой величины &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; или полученное значение не сильно отличается от значений, полученных на предыдущих циклах.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 4&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Пересчёт кластерных центров&#039;&#039;&#039; выполняется в соответствии со следующим уравнением:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;|C_i|&amp;lt;/math&amp;gt; подразумевается количество элементов в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом кластере.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 5&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Переход по циклу&#039;&#039;&#039; на шаг 2.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма составляют вычисления квадратов нормы расстояния от каждого из векторов исходной выборки до промежуточных кластерных центров &amp;lt;math&amp;gt;\|u_k-c_i\|^2&amp;lt;/math&amp;gt;. На каждой итерации алгоритма происходит расчёт &amp;lt;math&amp;gt;CN&amp;lt;/math&amp;gt; таких расстояний.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Основной операцией, выполняемой в алгоритме, как сказано выше, является операция нахождения квадратов расстояний между векторами данных и кластерными центрами. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
d_{ki} = \|u_k-c_i\|^2&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также на шаге вычисления объектной функции производится множественное суммирование полученных расстояний:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^C J_i = \sum\limits_{i=1}^C \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right),&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
а на шаге расчета кластерных центров происходит суммирование векторов:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Реализация последовательного алгоритма состоит в итеративном повторении блока, описанного далее в форме псевдокода, до тех пор, пока не будет достигнута желаемая точность.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;&lt;br /&gt;
J = 0;&lt;br /&gt;
M = zeros(N,C);&lt;br /&gt;
for i = 1 to N //go through every element&lt;br /&gt;
   d_min = MAXINT;&lt;br /&gt;
   j_min = 1;&lt;br /&gt;
   for j = 1 to C //deside which claster does element belong to&lt;br /&gt;
      d_ij  = sq_norm(u[i] - c[j]);&lt;br /&gt;
      if d_ij &amp;lt; d_min&lt;br /&gt;
         d_min = d_ij;&lt;br /&gt;
         j_min = j;&lt;br /&gt;
   //generation of output data&lt;br /&gt;
   J += d_min; &lt;br /&gt;
   M[i,j_min] = 1;&lt;br /&gt;
   c_new[j] += u[i];&lt;br /&gt;
   c_newCount[k]++;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
На каждой итерации алгоритма требуется выполнение:&lt;br /&gt;
* &amp;lt;math&amp;gt;NC&amp;lt;/math&amp;gt; операций вычисления квадрата нормы разности элементов;&lt;br /&gt;
* &amp;lt;math&amp;gt;NC&amp;lt;/math&amp;gt; операций сравнения (вычитаний);&lt;br /&gt;
* &amp;lt;math&amp;gt;3N&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
&lt;br /&gt;
Каждая операция вычисления нормы разности векторов предполагает выполнение &amp;lt;math&amp;gt;2n-1&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания и &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; операций возведения в квадрат (умножений), поэтому получаем для каждой итерации:&lt;br /&gt;
* &amp;lt;math&amp;gt;(2n-1)NC&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания;&lt;br /&gt;
* &amp;lt;math&amp;gt;(3+(n+1)C)N&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
&lt;br /&gt;
Ожидая, что предельная точность будет достигнута менее, чем за &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; итераций (в противном случае применение алгоритма можно считать нецелесообразным), получаем итоговую сложность последовательной реализации алгоритма &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt; (в предположении, что &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; существенно меньше &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
[[File:HardCMeans1.png|thumb|800px|center|Рисунок 1. Информационный граф алгоритма. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (&amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; стартовых значений кластерных центров и 1 значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; на каждую вершину графа), &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039; — вычисление минимального расстояния до кластерных центров (подробнее см. рисунок 2), &#039;&#039;&#039;&#039;&#039;M&#039;&#039;&#039;&#039;&#039; — запись единички в соответствующую строчку матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, &#039;&#039;&#039;&#039;&#039;J&#039;&#039;&#039;&#039;&#039; — вычисление объектной функции по результатам полученных вычислений, &#039;&#039;&#039;&#039;&#039;if&#039;&#039;&#039;&#039;&#039; — проверка условия достижения заданной точности, &#039;&#039;&#039;&#039;&#039;{c}&#039;&#039;&#039;&#039;&#039; — пересчёт кластерных центров и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; значений полученных кластерных центров).]]&lt;br /&gt;
[[File:HardCMeans2.PNG|thumb|400px|center|Рисунок 2. Подробное описание работы блока  &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039;. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (1 значение центра кластера на каждую из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; соответствующих вершин графа и значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;), &#039;&#039;&#039;&#039;&#039;d1,...,dC&#039;&#039;&#039;&#039;&#039; — прямое вычисление  расстояния до кластерных центров, &#039;&#039;&#039;&#039;&#039;max&#039;&#039;&#039;&#039;&#039; — вычисление максимума двух чисел (с сохранением соответствующего максимуму кластерного индекса) и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (индекс кластерного центра, расположенного ближе всего к точке &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;, и соответствующее расстояние).]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
Для выполнения одной итерации алгоритма C средних необходимо выполнить параллельно ряд вычислений для каждого из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; элементов:&lt;br /&gt;
&lt;br /&gt;
1. Вычисление &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; расстояний между элементом и кластерными центрами.&lt;br /&gt;
&lt;br /&gt;
2. Выполнение &amp;lt;math&amp;gt;(c - 1)&amp;lt;/math&amp;gt; сравнений для определения минимального.&lt;br /&gt;
&lt;br /&gt;
3. Определение значений столбца матрицы принадлежности &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, соответствующей элементу.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; &lt;br /&gt;
*&amp;lt;math&amp;gt;\{u_k\}_{k=1}^{n} \subset \mathbb{R}^m&amp;lt;/math&amp;gt; — исходный набор векторов;&lt;br /&gt;
*&amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; — желаемое количество кластеров (&amp;lt;math&amp;gt;2 \leqslant c \leqslant n&amp;lt;/math&amp;gt;);&lt;br /&gt;
* &#039;&#039;(опционально)&#039;&#039; &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; — пороговая точность работы алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;mn+1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
*&amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; — рядовая матрица из пространства &amp;lt;math&amp;gt;\mathbb{R}^{c \times n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;cn&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Назначение:&#039;&#039;&#039; кластеризация больших наборов числовых данных.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Достоинства:&#039;&#039;&#039;&lt;br /&gt;
* лёгкость реализации;&lt;br /&gt;
* вычислительная простота.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Недостатки:&#039;&#039;&#039;&lt;br /&gt;
* нет гарантии, что итеративный процесс сойдётся к оптимальному решению;&lt;br /&gt;
* производительность существенно зависит от выбора начальных кластерных центров.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
1)  [https://github.com/artpar/Hard-Clustering-implementation Последовательная реализация на С++ ]&lt;br /&gt;
&lt;br /&gt;
2) [http://projects.jasmeet.me/2013/03/HardCMeans.html Последовательная реализация на MatLab ]&lt;br /&gt;
&lt;br /&gt;
Параллельных реализаций в свободном доступе обнаружено не было.&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Юрий Комаров</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=8038</id>
		<title>Участник:Светлана Лукьяненко/Строгий алгоритм С средних (Hard C-Means, HCM)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=8038"/>
		<updated>2016-10-14T19:27:10Z</updated>

		<summary type="html">&lt;p&gt;Юрий Комаров: /* Последовательная сложность алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Строгий алгоритм С средних (Hard C-Means,HCM)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;-&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;-&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mn+1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;cn&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы описания: [[Участник:Светлана_Лукьяненко|Лукьяненко Светлана]], [[Участник:Юрий_Комаров|Комаров Юрий]].&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Строгий алгоритм C средних&#039;&#039;&#039; (&#039;&#039;&#039;&#039;&#039;Hard C-Means&#039;&#039;&#039;&#039;&#039;; &#039;&#039;Jang, Sun and Mizutani, 1997&#039;&#039;) позволяет распределить большие наборы числовых данных по кластерам в многомерном пространстве&amp;lt;ref&amp;gt;Jan Jantzen «Neurofuzzy Modelling». Электронное издание.&amp;lt;/ref&amp;gt;. Алгоритм является управляемым, так как для работы с ним требуется задание одного параметра — числа кластеров, на которое необходимо разделить данные. &lt;br /&gt;
Входными данными для алгоритма являются набор векторов и количество кластеров, также может задаваться пороговое значение величины объектной функции, по достижении которого расчёт прекращается. Выходными данными для алгоритма является рядовая матрица, отображающая принадлежность исходных элементов построенным кластерам, и центры построенных кластеров.&lt;br /&gt;
&lt;br /&gt;
Первым шагом выполнения алгоритма является инициализация центров кластеров случайными значениями. Дальнейшие шаги алгоритма выполняются итеративно до тех пор, пока объектная функция не станет меньше порогового значения или же значение объектной функции не будет минимально отличаться от полученного на предыдущей итерации. На каждой итерации вычислений выполняются следующие действия:&lt;br /&gt;
&lt;br /&gt;
# Расчёт рядовой матрицы, сопоставляющей каждый вектор с ближайшим кластерным центром.&lt;br /&gt;
# Расчёт объектной функции; проверка условий остановки и завершение расчёта в случае их выполнения.&lt;br /&gt;
# Пересчёт кластерных центров.&lt;br /&gt;
&lt;br /&gt;
Так как алгоритм является итеративным и зависит от начальных значений кластерных центров, он может не сходиться к локальному минимуму.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
==== Входные и выходные данные ====&lt;br /&gt;
На вход подаётся набор векторов &amp;lt;math&amp;gt;\{u_k\}_{k=1}^{N}&amp;lt;/math&amp;gt; пространства &amp;lt;math&amp;gt;\mathbb{R}^n&amp;lt;/math&amp;gt; и количество кластеров &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Конечным результатом работы алгоритма являются построенная рядовая матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, содержащая информацию о принадлежности элементов кластерам:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ij} = \begin{cases}&lt;br /&gt;
1, &amp;amp; u_j \in C_i, \\&lt;br /&gt;
0, &amp;amp; \text{otherwise},&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; подразумевается &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый построенный кластер, и набор &amp;lt;math&amp;gt;\{c_i\}_{i=1}^{C}&amp;lt;/math&amp;gt; центров этих кластеров.&lt;br /&gt;
&lt;br /&gt;
==== Описание алгоритма ====&lt;br /&gt;
Алгоритм состоит из 5 последовательных шагов.&amp;lt;ref&amp;gt; Нейский И.М. Классификация и сравнение методов кластеризации.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 1&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация кластерных центров&#039;&#039;&#039; &amp;lt;math&amp;gt;c_i \, (i=1,2,\ldots,C)&amp;lt;/math&amp;gt; может происходить за счёт случайного выбора необходимого числа точек из входного набора либо путём явного указания.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 2&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вычисление рядовой матрицы&#039;&#039;&#039; &amp;lt;math&amp;gt;M = \|m_{ik}\|&amp;lt;/math&amp;gt;, элементы которой задаются следующими выражениями (&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; — количество элементов во входном наборе данных):&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ik} = \begin{cases}&lt;br /&gt;
1, &amp;amp; \|u_k-c_i\|^2 \leqslant \|u_k-c_j\|^2 \;\; \text{for all } i \neq j; \;\; (i=1,2,\ldots,C; \; k = 1,2,\ldots,N)\\&lt;br /&gt;
0, &amp;amp; \text{otherwise}.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;!-- При этом, как легко видеть, матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; обладает следующими свойствами:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\sum\limits_{i=1}^C m_{ij} = 1, \;\; \sum\limits_{i=1}^C\sum\limits_{j=1}^K m_{ij} = K.&lt;br /&gt;
&amp;lt;/math&amp;gt; --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Будем говорить, что &amp;lt;math&amp;gt;u_k \in C_i&amp;lt;/math&amp;gt;, если &amp;lt;math&amp;gt;m_{ik} = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 3&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Расчёт объектной функции:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^C J_i = \sum\limits_{i=1}^C \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right)&lt;br /&gt;
.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На этом шаге происходит &#039;&#039;&#039;&amp;lt;u&amp;gt;остановка и выход из цикла&amp;lt;/u&amp;gt;&#039;&#039;&#039;, если полученное значение ниже пороговой величины &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; или полученное значение не сильно отличается от значений, полученных на предыдущих циклах.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 4&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Пересчёт кластерных центров&#039;&#039;&#039; выполняется в соответствии со следующим уравнением:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;|C_i|&amp;lt;/math&amp;gt; подразумевается количество элементов в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом кластере.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 5&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Переход по циклу&#039;&#039;&#039; на шаг 2.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма составляют вычисления квадратов нормы расстояния от каждого из векторов исходной выборки до промежуточных кластерных центров &amp;lt;math&amp;gt;\|u_k-c_i\|^2&amp;lt;/math&amp;gt;. На каждой итерации алгоритма происходит расчёт &amp;lt;math&amp;gt;CN&amp;lt;/math&amp;gt; таких расстояний.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Основной операцией, выполняемой в алгоритме, как сказано выше, является операция нахождения квадратов расстояний между векторами данных и кластерными центрами. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
d_{ki} = \|u_k-c_i\|^2&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также на шаге вычисления объектной функции производится множественное суммирование полученных расстояний:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^C J_i = \sum\limits_{i=1}^C \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right),&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
а на шаге расчета кластерных центров происходит суммирование векторов:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Реализация последовательного алгоритма состоит в итеративном повторении блока, описанного далее в форме псевдокода, до тех пор, пока не будет достигнута желаемая точность.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;&lt;br /&gt;
J = 0;&lt;br /&gt;
M = zeros(N,C);&lt;br /&gt;
for i = 1 to N //go through every element&lt;br /&gt;
   d_min = MAXINT;&lt;br /&gt;
   j_min = 1;&lt;br /&gt;
   for j = 1 to C //deside which claster does element belong to&lt;br /&gt;
      d_ij  = sq_norm(u[i] - c[j]);&lt;br /&gt;
      if d_ij &amp;lt; d_min&lt;br /&gt;
         d_min = d_ij;&lt;br /&gt;
         j_min = j;&lt;br /&gt;
   //generation of output data&lt;br /&gt;
   J += d_min; &lt;br /&gt;
   M[i,j_min] = 1;&lt;br /&gt;
   c_new[j] += u[i];&lt;br /&gt;
   c_newCount[k]++;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
На каждой итерации алгоритма требуется выполнение:&lt;br /&gt;
* &amp;lt;math&amp;gt;NC&amp;lt;/math&amp;gt; операций вычисления квадрата нормы разности элементов;&lt;br /&gt;
* &amp;lt;math&amp;gt;NC&amp;lt;/math&amp;gt; операций сравнения (вычитаний);&lt;br /&gt;
* &amp;lt;math&amp;gt;3N&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
&lt;br /&gt;
Каждая операция вычисления нормы разности векторов предполагает выполнение &amp;lt;math&amp;gt;2n-1&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания и &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; операций возведения в квадрат (умножений), поэтому получаем для каждой итерации:&lt;br /&gt;
* &amp;lt;math&amp;gt;(2n-1)NC&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания;&lt;br /&gt;
* &amp;lt;math&amp;gt;(3+(n+1)C)N&amp;lt;/math&amp;gt; операций умножения.&lt;br /&gt;
&lt;br /&gt;
Ожидая, что предельная точность будет достигнута менее, чем за &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; итераций (в противном случае применение алгоритма можно считать нецелесообразным), получаем итоговую сложность последовательной реализации алгоритма &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt; (в предположении, что &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; существенно меньше &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
[[File:HardCMeans1.png|thumb|800px|center|Рисунок 1. Информационный граф алгоритма. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (&amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; стартовых значений кластерных центров и 1 значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; на каждую вершину графа), &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039; — вычисление минимального расстояния до кластерных центров (подробнее см. рисунок 2), &#039;&#039;&#039;&#039;&#039;M&#039;&#039;&#039;&#039;&#039; — запись единички в соответствующую строчку матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, &#039;&#039;&#039;&#039;&#039;J&#039;&#039;&#039;&#039;&#039; — вычисление объектной функции по результатам полученных вычислений, &#039;&#039;&#039;&#039;&#039;if&#039;&#039;&#039;&#039;&#039; — проверка условия достижения заданной точности, &#039;&#039;&#039;&#039;&#039;{c}&#039;&#039;&#039;&#039;&#039; — пересчёт кластерных центров и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; значений полученных кластерных центров).]]&lt;br /&gt;
[[File:HardCMeans2.PNG|thumb|400px|center|Рисунок 2. Подробное описание работы блока  &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039;. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (1 значение центра кластера на каждую из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; соответствующих вершин графа и значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;), &#039;&#039;&#039;&#039;&#039;d1,...,dC&#039;&#039;&#039;&#039;&#039; — прямое вычисление  расстояния до кластерных центров, &#039;&#039;&#039;&#039;&#039;max&#039;&#039;&#039;&#039;&#039; — вычисление максимума двух чисел (с сохранением соответствующего максимуму кластерного индекса) и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (индекс кластерного центра, расположенного ближе всего к точке &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;, и соответствующее расстояние).]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
Для выполнения одной итерации алгоритма C средних необходимо выполнить параллельно ряд вычислений для каждого из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; элементов:&lt;br /&gt;
&lt;br /&gt;
1. Вычисление &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; расстояний между элементом и кластерными центрами.&lt;br /&gt;
&lt;br /&gt;
2. Выполнение &amp;lt;math&amp;gt;(c - 1)&amp;lt;/math&amp;gt; сравнений для определения минимального.&lt;br /&gt;
&lt;br /&gt;
3. Определение значений столбца матрицы принадлежности &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, соответствующей элементу.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; &lt;br /&gt;
*&amp;lt;math&amp;gt;\{u_k\}_{k=1}^{n} \subset \mathbb{R}^m&amp;lt;/math&amp;gt; — исходный набор векторов;&lt;br /&gt;
*&amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; — желаемое количество кластеров (&amp;lt;math&amp;gt;2 \leqslant c \leqslant n&amp;lt;/math&amp;gt;);&lt;br /&gt;
* &#039;&#039;(опционально)&#039;&#039; &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; — пороговая точность работы алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;mn+1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
*&amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; — рядовая матрица из пространства &amp;lt;math&amp;gt;\mathbb{R}^{c \times n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;cn&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Назначение:&#039;&#039;&#039; кластеризация больших наборов числовых данных.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Достоинства:&#039;&#039;&#039;&lt;br /&gt;
* лёгкость реализации;&lt;br /&gt;
* вычислительная простота.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Недостатки:&#039;&#039;&#039;&lt;br /&gt;
* нет гарантии, что итеративный процесс сойдётся к оптимальному решению;&lt;br /&gt;
* производительность существенно зависит от выбора начальных кластерных центров.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
1)  [https://github.com/artpar/Hard-Clustering-implementation Последовательная реализация на С++ ]&lt;br /&gt;
&lt;br /&gt;
2) [http://projects.jasmeet.me/2013/03/HardCMeans.html Последовательная реализация на MatLab ]&lt;br /&gt;
&lt;br /&gt;
Параллельных реализаций в свободном доступе обнаружено не было.&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Юрий Комаров</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=8015</id>
		<title>Участник:Светлана Лукьяненко/Строгий алгоритм С средних (Hard C-Means, HCM)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=8015"/>
		<updated>2016-10-14T19:20:58Z</updated>

		<summary type="html">&lt;p&gt;Юрий Комаров: /* Схема реализации последовательного алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Строгий алгоритм С средних (Hard C-Means,HCM)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;-&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;-&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mn+1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;cn&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы описания: [[Участник:Светлана_Лукьяненко|Лукьяненко Светлана]], [[Участник:Юрий_Комаров|Комаров Юрий]].&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Строгий алгоритм C средних&#039;&#039;&#039; (&#039;&#039;&#039;&#039;&#039;Hard C-Means&#039;&#039;&#039;&#039;&#039;; &#039;&#039;Jang, Sun and Mizutani, 1997&#039;&#039;) позволяет распределить большие наборы числовых данных по кластерам в многомерном пространстве&amp;lt;ref&amp;gt;Jan Jantzen «Neurofuzzy Modelling». Электронное издание.&amp;lt;/ref&amp;gt;. Алгоритм является управляемым, так как для работы с ним требуется задание одного параметра — числа кластеров, на которое необходимо разделить данные. &lt;br /&gt;
Входными данными для алгоритма являются набор векторов и количество кластеров, также может задаваться пороговое значение величины объектной функции, по достижении которого расчёт прекращается. Выходными данными для алгоритма является рядовая матрица, отображающая принадлежность исходных элементов построенным кластерам, и центры построенных кластеров.&lt;br /&gt;
&lt;br /&gt;
Первым шагом выполнения алгоритма является инициализация центров кластеров случайными значениями. Дальнейшие шаги алгоритма выполняются итеративно до тех пор, пока объектная функция не станет меньше порогового значения или же значение объектной функции не будет минимально отличаться от полученного на предыдущей итерации. На каждой итерации вычислений выполняются следующие действия:&lt;br /&gt;
&lt;br /&gt;
# Расчёт рядовой матрицы, сопоставляющей каждый вектор с ближайшим кластерным центром.&lt;br /&gt;
# Расчёт объектной функции; проверка условий остановки и завершение расчёта в случае их выполнения.&lt;br /&gt;
# Пересчёт кластерных центров.&lt;br /&gt;
&lt;br /&gt;
Так как алгоритм является итеративным и зависит от начальных значений кластерных центров, он может не сходиться к локальному минимуму.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
==== Входные и выходные данные ====&lt;br /&gt;
На вход подаётся набор векторов &amp;lt;math&amp;gt;\{u_k\}_{k=1}^{N}&amp;lt;/math&amp;gt; пространства &amp;lt;math&amp;gt;\mathbb{R}^n&amp;lt;/math&amp;gt; и количество кластеров &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Конечным результатом работы алгоритма являются построенная рядовая матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, содержащая информацию о принадлежности элементов кластерам:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ij} = \begin{cases}&lt;br /&gt;
1, &amp;amp; u_j \in C_i, \\&lt;br /&gt;
0, &amp;amp; \text{otherwise},&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; подразумевается &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый построенный кластер, и набор &amp;lt;math&amp;gt;\{c_i\}_{i=1}^{C}&amp;lt;/math&amp;gt; центров этих кластеров.&lt;br /&gt;
&lt;br /&gt;
==== Описание алгоритма ====&lt;br /&gt;
Алгоритм состоит из 5 последовательных шагов.&amp;lt;ref&amp;gt; Нейский И.М. Классификация и сравнение методов кластеризации.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 1&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация кластерных центров&#039;&#039;&#039; &amp;lt;math&amp;gt;c_i \, (i=1,2,\ldots,C)&amp;lt;/math&amp;gt; может происходить за счёт случайного выбора необходимого числа точек из входного набора либо путём явного указания.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 2&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вычисление рядовой матрицы&#039;&#039;&#039; &amp;lt;math&amp;gt;M = \|m_{ik}\|&amp;lt;/math&amp;gt;, элементы которой задаются следующими выражениями (&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; — количество элементов во входном наборе данных):&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ik} = \begin{cases}&lt;br /&gt;
1, &amp;amp; \|u_k-c_i\|^2 \leqslant \|u_k-c_j\|^2 \;\; \text{for all } i \neq j; \;\; (i=1,2,\ldots,C; \; k = 1,2,\ldots,N)\\&lt;br /&gt;
0, &amp;amp; \text{otherwise}.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;!-- При этом, как легко видеть, матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; обладает следующими свойствами:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\sum\limits_{i=1}^C m_{ij} = 1, \;\; \sum\limits_{i=1}^C\sum\limits_{j=1}^K m_{ij} = K.&lt;br /&gt;
&amp;lt;/math&amp;gt; --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Будем говорить, что &amp;lt;math&amp;gt;u_k \in C_i&amp;lt;/math&amp;gt;, если &amp;lt;math&amp;gt;m_{ik} = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 3&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Расчёт объектной функции:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^C J_i = \sum\limits_{i=1}^C \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right)&lt;br /&gt;
.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На этом шаге происходит &#039;&#039;&#039;&amp;lt;u&amp;gt;остановка и выход из цикла&amp;lt;/u&amp;gt;&#039;&#039;&#039;, если полученное значение ниже пороговой величины &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; или полученное значение не сильно отличается от значений, полученных на предыдущих циклах.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 4&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Пересчёт кластерных центров&#039;&#039;&#039; выполняется в соответствии со следующим уравнением:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;|C_i|&amp;lt;/math&amp;gt; подразумевается количество элементов в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом кластере.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 5&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Переход по циклу&#039;&#039;&#039; на шаг 2.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма составляют вычисления квадратов нормы расстояния от каждого из векторов исходной выборки до промежуточных кластерных центров &amp;lt;math&amp;gt;\|u_k-c_i\|^2&amp;lt;/math&amp;gt;. На каждой итерации алгоритма происходит расчёт &amp;lt;math&amp;gt;CN&amp;lt;/math&amp;gt; таких расстояний.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Основной операцией, выполняемой в алгоритме, как сказано выше, является операция нахождения квадратов расстояний между векторами данных и кластерными центрами. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
d_{ki} = \|u_k-c_i\|^2&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также на шаге вычисления объектной функции производится множественное суммирование полученных расстояний:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^C J_i = \sum\limits_{i=1}^C \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right),&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
а на шаге расчета кластерных центров происходит суммирование векторов:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Реализация последовательного алгоритма состоит в итеративном повторении блока, описанного далее в форме псевдокода, до тех пор, пока не будет достигнута желаемая точность.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;&lt;br /&gt;
J = 0;&lt;br /&gt;
M = zeros(N,C);&lt;br /&gt;
for i = 1 to N //go through every element&lt;br /&gt;
   d_min = MAXINT;&lt;br /&gt;
   j_min = 1;&lt;br /&gt;
   for j = 1 to C //deside which claster does element belong to&lt;br /&gt;
      d_ij  = sq_norm(u[i] - c[j]);&lt;br /&gt;
      if d_ij &amp;lt; d_min&lt;br /&gt;
         d_min = d_ij;&lt;br /&gt;
         j_min = j;&lt;br /&gt;
   //generation of output data&lt;br /&gt;
   J += d_min; &lt;br /&gt;
   M[i,j_min] = 1;&lt;br /&gt;
   c_new[j] += u[i];&lt;br /&gt;
   c_newCount[k]++;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
На каждой итерации алгоритма требуется выполнение:&lt;br /&gt;
* &amp;lt;math&amp;gt;nC&amp;lt;/math&amp;gt; операций вычисления квадрата нормы разности элементов;&lt;br /&gt;
* &amp;lt;math&amp;gt;nC&amp;lt;/math&amp;gt; операций сравнения (вычитаний);&lt;br /&gt;
* &amp;lt;math&amp;gt;3n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
&lt;br /&gt;
Преполагая, что операция вычисления нормы вектора предполагает выполнение &amp;lt;math&amp;gt;2m&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания и &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; операций возведения в квадрат (умножений), получаем, что реализация алгоритма требует выполнения&lt;br /&gt;
* &amp;lt;math&amp;gt;2mnC&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания;&lt;br /&gt;
* &amp;lt;math&amp;gt;(3+(m+1)C)n&amp;lt;/math&amp;gt; операций умножения&lt;br /&gt;
на каждой итерации цикла.&lt;br /&gt;
&lt;br /&gt;
Ожидая, что предельная точность будет достигнута не более, чем за &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; итераций (что соответствует объёму исходной выборки), получаем итоговую сложность последовательной реализации алгоритма &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
[[File:HardCMeans1.png|thumb|800px|center|Рисунок 1. Информационный граф алгоритма. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (&amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; стартовых значений кластерных центров и 1 значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; на каждую вершину графа), &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039; — вычисление минимального расстояния до кластерных центров (подробнее см. рисунок 2), &#039;&#039;&#039;&#039;&#039;M&#039;&#039;&#039;&#039;&#039; — запись единички в соответствующую строчку матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, &#039;&#039;&#039;&#039;&#039;J&#039;&#039;&#039;&#039;&#039; — вычисление объектной функции по результатам полученных вычислений, &#039;&#039;&#039;&#039;&#039;if&#039;&#039;&#039;&#039;&#039; — проверка условия достижения заданной точности, &#039;&#039;&#039;&#039;&#039;{c}&#039;&#039;&#039;&#039;&#039; — пересчёт кластерных центров и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; значений полученных кластерных центров).]]&lt;br /&gt;
[[File:HardCMeans2.PNG|thumb|400px|center|Рисунок 2. Подробное описание работы блока  &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039;. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (1 значение центра кластера на каждую из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; соответствующих вершин графа и значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;), &#039;&#039;&#039;&#039;&#039;d1,...,dC&#039;&#039;&#039;&#039;&#039; — прямое вычисление  расстояния до кластерных центров, &#039;&#039;&#039;&#039;&#039;max&#039;&#039;&#039;&#039;&#039; — вычисление максимума двух чисел (с сохранением соответствующего максимуму кластерного индекса) и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (индекс кластерного центра, расположенного ближе всего к точке &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;, и соответствующее расстояние).]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
Для выполнения одной итерации алгоритма C средних необходимо выполнить параллельно ряд вычислений для каждого из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; элементов:&lt;br /&gt;
&lt;br /&gt;
1. Вычисление &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; расстояний между элементом и кластерными центрами.&lt;br /&gt;
&lt;br /&gt;
2. Выполнение &amp;lt;math&amp;gt;(c - 1)&amp;lt;/math&amp;gt; сравнений для определения минимального.&lt;br /&gt;
&lt;br /&gt;
3. Определение значений столбца матрицы принадлежности &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, соответствующей элементу.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; &lt;br /&gt;
*&amp;lt;math&amp;gt;\{u_k\}_{k=1}^{n} \subset \mathbb{R}^m&amp;lt;/math&amp;gt; — исходный набор векторов;&lt;br /&gt;
*&amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; — желаемое количество кластеров (&amp;lt;math&amp;gt;2 \leqslant c \leqslant n&amp;lt;/math&amp;gt;);&lt;br /&gt;
* &#039;&#039;(опционально)&#039;&#039; &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; — пороговая точность работы алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;mn+1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
*&amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; — рядовая матрица из пространства &amp;lt;math&amp;gt;\mathbb{R}^{c \times n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;cn&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Назначение:&#039;&#039;&#039; кластеризация больших наборов числовых данных.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Достоинства:&#039;&#039;&#039;&lt;br /&gt;
* лёгкость реализации;&lt;br /&gt;
* вычислительная простота.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Недостатки:&#039;&#039;&#039;&lt;br /&gt;
* нет гарантии, что итеративный процесс сойдётся к оптимальному решению;&lt;br /&gt;
* производительность существенно зависит от выбора начальных кластерных центров.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Юрий Комаров</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=8011</id>
		<title>Участник:Светлана Лукьяненко/Строгий алгоритм С средних (Hard C-Means, HCM)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=8011"/>
		<updated>2016-10-14T19:20:17Z</updated>

		<summary type="html">&lt;p&gt;Юрий Комаров: /* Макроструктура алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Строгий алгоритм С средних (Hard C-Means,HCM)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;-&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;-&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mn+1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;cn&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы описания: [[Участник:Светлана_Лукьяненко|Лукьяненко Светлана]], [[Участник:Юрий_Комаров|Комаров Юрий]].&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Строгий алгоритм C средних&#039;&#039;&#039; (&#039;&#039;&#039;&#039;&#039;Hard C-Means&#039;&#039;&#039;&#039;&#039;; &#039;&#039;Jang, Sun and Mizutani, 1997&#039;&#039;) позволяет распределить большие наборы числовых данных по кластерам в многомерном пространстве&amp;lt;ref&amp;gt;Jan Jantzen «Neurofuzzy Modelling». Электронное издание.&amp;lt;/ref&amp;gt;. Алгоритм является управляемым, так как для работы с ним требуется задание одного параметра — числа кластеров, на которое необходимо разделить данные. &lt;br /&gt;
Входными данными для алгоритма являются набор векторов и количество кластеров, также может задаваться пороговое значение величины объектной функции, по достижении которого расчёт прекращается. Выходными данными для алгоритма является рядовая матрица, отображающая принадлежность исходных элементов построенным кластерам, и центры построенных кластеров.&lt;br /&gt;
&lt;br /&gt;
Первым шагом выполнения алгоритма является инициализация центров кластеров случайными значениями. Дальнейшие шаги алгоритма выполняются итеративно до тех пор, пока объектная функция не станет меньше порогового значения или же значение объектной функции не будет минимально отличаться от полученного на предыдущей итерации. На каждой итерации вычислений выполняются следующие действия:&lt;br /&gt;
&lt;br /&gt;
# Расчёт рядовой матрицы, сопоставляющей каждый вектор с ближайшим кластерным центром.&lt;br /&gt;
# Расчёт объектной функции; проверка условий остановки и завершение расчёта в случае их выполнения.&lt;br /&gt;
# Пересчёт кластерных центров.&lt;br /&gt;
&lt;br /&gt;
Так как алгоритм является итеративным и зависит от начальных значений кластерных центров, он может не сходиться к локальному минимуму.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
==== Входные и выходные данные ====&lt;br /&gt;
На вход подаётся набор векторов &amp;lt;math&amp;gt;\{u_k\}_{k=1}^{N}&amp;lt;/math&amp;gt; пространства &amp;lt;math&amp;gt;\mathbb{R}^n&amp;lt;/math&amp;gt; и количество кластеров &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Конечным результатом работы алгоритма являются построенная рядовая матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, содержащая информацию о принадлежности элементов кластерам:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ij} = \begin{cases}&lt;br /&gt;
1, &amp;amp; u_j \in C_i, \\&lt;br /&gt;
0, &amp;amp; \text{otherwise},&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; подразумевается &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый построенный кластер, и набор &amp;lt;math&amp;gt;\{c_i\}_{i=1}^{C}&amp;lt;/math&amp;gt; центров этих кластеров.&lt;br /&gt;
&lt;br /&gt;
==== Описание алгоритма ====&lt;br /&gt;
Алгоритм состоит из 5 последовательных шагов.&amp;lt;ref&amp;gt; Нейский И.М. Классификация и сравнение методов кластеризации.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 1&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация кластерных центров&#039;&#039;&#039; &amp;lt;math&amp;gt;c_i \, (i=1,2,\ldots,C)&amp;lt;/math&amp;gt; может происходить за счёт случайного выбора необходимого числа точек из входного набора либо путём явного указания.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 2&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вычисление рядовой матрицы&#039;&#039;&#039; &amp;lt;math&amp;gt;M = \|m_{ik}\|&amp;lt;/math&amp;gt;, элементы которой задаются следующими выражениями (&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; — количество элементов во входном наборе данных):&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ik} = \begin{cases}&lt;br /&gt;
1, &amp;amp; \|u_k-c_i\|^2 \leqslant \|u_k-c_j\|^2 \;\; \text{for all } i \neq j; \;\; (i=1,2,\ldots,C; \; k = 1,2,\ldots,N)\\&lt;br /&gt;
0, &amp;amp; \text{otherwise}.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;!-- При этом, как легко видеть, матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; обладает следующими свойствами:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\sum\limits_{i=1}^C m_{ij} = 1, \;\; \sum\limits_{i=1}^C\sum\limits_{j=1}^K m_{ij} = K.&lt;br /&gt;
&amp;lt;/math&amp;gt; --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Будем говорить, что &amp;lt;math&amp;gt;u_k \in C_i&amp;lt;/math&amp;gt;, если &amp;lt;math&amp;gt;m_{ik} = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 3&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Расчёт объектной функции:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^C J_i = \sum\limits_{i=1}^C \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right)&lt;br /&gt;
.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На этом шаге происходит &#039;&#039;&#039;&amp;lt;u&amp;gt;остановка и выход из цикла&amp;lt;/u&amp;gt;&#039;&#039;&#039;, если полученное значение ниже пороговой величины &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; или полученное значение не сильно отличается от значений, полученных на предыдущих циклах.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 4&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Пересчёт кластерных центров&#039;&#039;&#039; выполняется в соответствии со следующим уравнением:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;|C_i|&amp;lt;/math&amp;gt; подразумевается количество элементов в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом кластере.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 5&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Переход по циклу&#039;&#039;&#039; на шаг 2.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма составляют вычисления квадратов нормы расстояния от каждого из векторов исходной выборки до промежуточных кластерных центров &amp;lt;math&amp;gt;\|u_k-c_i\|^2&amp;lt;/math&amp;gt;. На каждой итерации алгоритма происходит расчёт &amp;lt;math&amp;gt;CN&amp;lt;/math&amp;gt; таких расстояний.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Основной операцией, выполняемой в алгоритме, как сказано выше, является операция нахождения квадратов расстояний между векторами данных и кластерными центрами. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
d_{ki} = \|u_k-c_i\|^2&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также на шаге вычисления объектной функции производится множественное суммирование полученных расстояний:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^C J_i = \sum\limits_{i=1}^C \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right),&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
а на шаге расчета кластерных центров происходит суммирование векторов:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Реализация последовательного алгоритма состоит в итеративном повторении блока, описанного далее в форме псевдокода, до тех пор, пока не будет достигнута желаемая точность.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;&lt;br /&gt;
J = 0;&lt;br /&gt;
M = zeros(n,C);&lt;br /&gt;
for i = 1 to n //go through every element&lt;br /&gt;
   d_min = MAXINT;&lt;br /&gt;
   j_min = 1;&lt;br /&gt;
   for j = 1 to C //deside which claster does element belong to&lt;br /&gt;
      d_ij  = sq_norm(u[i] - c[j]);&lt;br /&gt;
      if d_ij &amp;lt; d_min&lt;br /&gt;
         d_min = d_ij;&lt;br /&gt;
         j_min = j;&lt;br /&gt;
   //generation of output data&lt;br /&gt;
   J += d_min; &lt;br /&gt;
   M[i,j_min] = 1;&lt;br /&gt;
   c_new[j] += u[i];&lt;br /&gt;
   c_newCount[k]++;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
На каждой итерации алгоритма требуется выполнение:&lt;br /&gt;
* &amp;lt;math&amp;gt;nC&amp;lt;/math&amp;gt; операций вычисления квадрата нормы разности элементов;&lt;br /&gt;
* &amp;lt;math&amp;gt;nC&amp;lt;/math&amp;gt; операций сравнения (вычитаний);&lt;br /&gt;
* &amp;lt;math&amp;gt;3n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
&lt;br /&gt;
Преполагая, что операция вычисления нормы вектора предполагает выполнение &amp;lt;math&amp;gt;2m&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания и &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; операций возведения в квадрат (умножений), получаем, что реализация алгоритма требует выполнения&lt;br /&gt;
* &amp;lt;math&amp;gt;2mnC&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания;&lt;br /&gt;
* &amp;lt;math&amp;gt;(3+(m+1)C)n&amp;lt;/math&amp;gt; операций умножения&lt;br /&gt;
на каждой итерации цикла.&lt;br /&gt;
&lt;br /&gt;
Ожидая, что предельная точность будет достигнута не более, чем за &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; итераций (что соответствует объёму исходной выборки), получаем итоговую сложность последовательной реализации алгоритма &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
[[File:HardCMeans1.png|thumb|800px|center|Рисунок 1. Информационный граф алгоритма. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (&amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; стартовых значений кластерных центров и 1 значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; на каждую вершину графа), &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039; — вычисление минимального расстояния до кластерных центров (подробнее см. рисунок 2), &#039;&#039;&#039;&#039;&#039;M&#039;&#039;&#039;&#039;&#039; — запись единички в соответствующую строчку матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, &#039;&#039;&#039;&#039;&#039;J&#039;&#039;&#039;&#039;&#039; — вычисление объектной функции по результатам полученных вычислений, &#039;&#039;&#039;&#039;&#039;if&#039;&#039;&#039;&#039;&#039; — проверка условия достижения заданной точности, &#039;&#039;&#039;&#039;&#039;{c}&#039;&#039;&#039;&#039;&#039; — пересчёт кластерных центров и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; значений полученных кластерных центров).]]&lt;br /&gt;
[[File:HardCMeans2.PNG|thumb|400px|center|Рисунок 2. Подробное описание работы блока  &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039;. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (1 значение центра кластера на каждую из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; соответствующих вершин графа и значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;), &#039;&#039;&#039;&#039;&#039;d1,...,dC&#039;&#039;&#039;&#039;&#039; — прямое вычисление  расстояния до кластерных центров, &#039;&#039;&#039;&#039;&#039;max&#039;&#039;&#039;&#039;&#039; — вычисление максимума двух чисел (с сохранением соответствующего максимуму кластерного индекса) и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (индекс кластерного центра, расположенного ближе всего к точке &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;, и соответствующее расстояние).]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
Для выполнения одной итерации алгоритма C средних необходимо выполнить параллельно ряд вычислений для каждого из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; элементов:&lt;br /&gt;
&lt;br /&gt;
1. Вычисление &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; расстояний между элементом и кластерными центрами.&lt;br /&gt;
&lt;br /&gt;
2. Выполнение &amp;lt;math&amp;gt;(c - 1)&amp;lt;/math&amp;gt; сравнений для определения минимального.&lt;br /&gt;
&lt;br /&gt;
3. Определение значений столбца матрицы принадлежности &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, соответствующей элементу.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; &lt;br /&gt;
*&amp;lt;math&amp;gt;\{u_k\}_{k=1}^{n} \subset \mathbb{R}^m&amp;lt;/math&amp;gt; — исходный набор векторов;&lt;br /&gt;
*&amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; — желаемое количество кластеров (&amp;lt;math&amp;gt;2 \leqslant c \leqslant n&amp;lt;/math&amp;gt;);&lt;br /&gt;
* &#039;&#039;(опционально)&#039;&#039; &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; — пороговая точность работы алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;mn+1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
*&amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; — рядовая матрица из пространства &amp;lt;math&amp;gt;\mathbb{R}^{c \times n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;cn&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Назначение:&#039;&#039;&#039; кластеризация больших наборов числовых данных.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Достоинства:&#039;&#039;&#039;&lt;br /&gt;
* лёгкость реализации;&lt;br /&gt;
* вычислительная простота.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Недостатки:&#039;&#039;&#039;&lt;br /&gt;
* нет гарантии, что итеративный процесс сойдётся к оптимальному решению;&lt;br /&gt;
* производительность существенно зависит от выбора начальных кластерных центров.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Юрий Комаров</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=8008</id>
		<title>Участник:Светлана Лукьяненко/Строгий алгоритм С средних (Hard C-Means, HCM)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=8008"/>
		<updated>2016-10-14T19:19:42Z</updated>

		<summary type="html">&lt;p&gt;Юрий Комаров: /* Входные и выходные данные */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Строгий алгоритм С средних (Hard C-Means,HCM)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;-&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;-&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mn+1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;cn&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы описания: [[Участник:Светлана_Лукьяненко|Лукьяненко Светлана]], [[Участник:Юрий_Комаров|Комаров Юрий]].&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Строгий алгоритм C средних&#039;&#039;&#039; (&#039;&#039;&#039;&#039;&#039;Hard C-Means&#039;&#039;&#039;&#039;&#039;; &#039;&#039;Jang, Sun and Mizutani, 1997&#039;&#039;) позволяет распределить большие наборы числовых данных по кластерам в многомерном пространстве&amp;lt;ref&amp;gt;Jan Jantzen «Neurofuzzy Modelling». Электронное издание.&amp;lt;/ref&amp;gt;. Алгоритм является управляемым, так как для работы с ним требуется задание одного параметра — числа кластеров, на которое необходимо разделить данные. &lt;br /&gt;
Входными данными для алгоритма являются набор векторов и количество кластеров, также может задаваться пороговое значение величины объектной функции, по достижении которого расчёт прекращается. Выходными данными для алгоритма является рядовая матрица, отображающая принадлежность исходных элементов построенным кластерам, и центры построенных кластеров.&lt;br /&gt;
&lt;br /&gt;
Первым шагом выполнения алгоритма является инициализация центров кластеров случайными значениями. Дальнейшие шаги алгоритма выполняются итеративно до тех пор, пока объектная функция не станет меньше порогового значения или же значение объектной функции не будет минимально отличаться от полученного на предыдущей итерации. На каждой итерации вычислений выполняются следующие действия:&lt;br /&gt;
&lt;br /&gt;
# Расчёт рядовой матрицы, сопоставляющей каждый вектор с ближайшим кластерным центром.&lt;br /&gt;
# Расчёт объектной функции; проверка условий остановки и завершение расчёта в случае их выполнения.&lt;br /&gt;
# Пересчёт кластерных центров.&lt;br /&gt;
&lt;br /&gt;
Так как алгоритм является итеративным и зависит от начальных значений кластерных центров, он может не сходиться к локальному минимуму.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
==== Входные и выходные данные ====&lt;br /&gt;
На вход подаётся набор векторов &amp;lt;math&amp;gt;\{u_k\}_{k=1}^{N}&amp;lt;/math&amp;gt; пространства &amp;lt;math&amp;gt;\mathbb{R}^n&amp;lt;/math&amp;gt; и количество кластеров &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Конечным результатом работы алгоритма являются построенная рядовая матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, содержащая информацию о принадлежности элементов кластерам:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ij} = \begin{cases}&lt;br /&gt;
1, &amp;amp; u_j \in C_i, \\&lt;br /&gt;
0, &amp;amp; \text{otherwise},&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; подразумевается &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый построенный кластер, и набор &amp;lt;math&amp;gt;\{c_i\}_{i=1}^{C}&amp;lt;/math&amp;gt; центров этих кластеров.&lt;br /&gt;
&lt;br /&gt;
==== Описание алгоритма ====&lt;br /&gt;
Алгоритм состоит из 5 последовательных шагов.&amp;lt;ref&amp;gt; Нейский И.М. Классификация и сравнение методов кластеризации.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 1&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация кластерных центров&#039;&#039;&#039; &amp;lt;math&amp;gt;c_i \, (i=1,2,\ldots,C)&amp;lt;/math&amp;gt; может происходить за счёт случайного выбора необходимого числа точек из входного набора либо путём явного указания.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 2&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вычисление рядовой матрицы&#039;&#039;&#039; &amp;lt;math&amp;gt;M = \|m_{ik}\|&amp;lt;/math&amp;gt;, элементы которой задаются следующими выражениями (&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; — количество элементов во входном наборе данных):&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ik} = \begin{cases}&lt;br /&gt;
1, &amp;amp; \|u_k-c_i\|^2 \leqslant \|u_k-c_j\|^2 \;\; \text{for all } i \neq j; \;\; (i=1,2,\ldots,C; \; k = 1,2,\ldots,N)\\&lt;br /&gt;
0, &amp;amp; \text{otherwise}.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;!-- При этом, как легко видеть, матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; обладает следующими свойствами:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\sum\limits_{i=1}^C m_{ij} = 1, \;\; \sum\limits_{i=1}^C\sum\limits_{j=1}^K m_{ij} = K.&lt;br /&gt;
&amp;lt;/math&amp;gt; --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Будем говорить, что &amp;lt;math&amp;gt;u_k \in C_i&amp;lt;/math&amp;gt;, если &amp;lt;math&amp;gt;m_{ik} = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 3&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Расчёт объектной функции:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^C J_i = \sum\limits_{i=1}^C \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right)&lt;br /&gt;
.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На этом шаге происходит &#039;&#039;&#039;&amp;lt;u&amp;gt;остановка и выход из цикла&amp;lt;/u&amp;gt;&#039;&#039;&#039;, если полученное значение ниже пороговой величины &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; или полученное значение не сильно отличается от значений, полученных на предыдущих циклах.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 4&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Пересчёт кластерных центров&#039;&#039;&#039; выполняется в соответствии со следующим уравнением:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;|C_i|&amp;lt;/math&amp;gt; подразумевается количество элементов в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом кластере.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 5&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Переход по циклу&#039;&#039;&#039; на шаг 2.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма составляют вычисления квадратов нормы расстояния от каждого из векторов исходной выборки до промежуточных кластерных центров &amp;lt;math&amp;gt;\|u_k-c_i\|^2&amp;lt;/math&amp;gt;. На каждой итерации алгоритма происходит расчёт &amp;lt;math&amp;gt;CN&amp;lt;/math&amp;gt; таких расстояний.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Основной операцией, выполняемой в алгоритме, как сказано выше, является операция нахождения квадратов расстояний между векторами данных и кластерными центрами. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
d_{ki} = \|u_k-c_i\|^2&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также на шаге вычисления объектной функции производится множественное суммирование полученных расстояний:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^c J_i = \sum\limits_{i=1}^c \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right),&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
а на шаге расчета кластерных центров происходит суммирование векторов:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Реализация последовательного алгоритма состоит в итеративном повторении блока, описанного далее в форме псевдокода, до тех пор, пока не будет достигнута желаемая точность.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;&lt;br /&gt;
J = 0;&lt;br /&gt;
M = zeros(n,C);&lt;br /&gt;
for i = 1 to n //go through every element&lt;br /&gt;
   d_min = MAXINT;&lt;br /&gt;
   j_min = 1;&lt;br /&gt;
   for j = 1 to C //deside which claster does element belong to&lt;br /&gt;
      d_ij  = sq_norm(u[i] - c[j]);&lt;br /&gt;
      if d_ij &amp;lt; d_min&lt;br /&gt;
         d_min = d_ij;&lt;br /&gt;
         j_min = j;&lt;br /&gt;
   //generation of output data&lt;br /&gt;
   J += d_min; &lt;br /&gt;
   M[i,j_min] = 1;&lt;br /&gt;
   c_new[j] += u[i];&lt;br /&gt;
   c_newCount[k]++;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
На каждой итерации алгоритма требуется выполнение:&lt;br /&gt;
* &amp;lt;math&amp;gt;nC&amp;lt;/math&amp;gt; операций вычисления квадрата нормы разности элементов;&lt;br /&gt;
* &amp;lt;math&amp;gt;nC&amp;lt;/math&amp;gt; операций сравнения (вычитаний);&lt;br /&gt;
* &amp;lt;math&amp;gt;3n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
&lt;br /&gt;
Преполагая, что операция вычисления нормы вектора предполагает выполнение &amp;lt;math&amp;gt;2m&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания и &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; операций возведения в квадрат (умножений), получаем, что реализация алгоритма требует выполнения&lt;br /&gt;
* &amp;lt;math&amp;gt;2mnC&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания;&lt;br /&gt;
* &amp;lt;math&amp;gt;(3+(m+1)C)n&amp;lt;/math&amp;gt; операций умножения&lt;br /&gt;
на каждой итерации цикла.&lt;br /&gt;
&lt;br /&gt;
Ожидая, что предельная точность будет достигнута не более, чем за &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; итераций (что соответствует объёму исходной выборки), получаем итоговую сложность последовательной реализации алгоритма &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
[[File:HardCMeans1.png|thumb|800px|center|Рисунок 1. Информационный граф алгоритма. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (&amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; стартовых значений кластерных центров и 1 значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; на каждую вершину графа), &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039; — вычисление минимального расстояния до кластерных центров (подробнее см. рисунок 2), &#039;&#039;&#039;&#039;&#039;M&#039;&#039;&#039;&#039;&#039; — запись единички в соответствующую строчку матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, &#039;&#039;&#039;&#039;&#039;J&#039;&#039;&#039;&#039;&#039; — вычисление объектной функции по результатам полученных вычислений, &#039;&#039;&#039;&#039;&#039;if&#039;&#039;&#039;&#039;&#039; — проверка условия достижения заданной точности, &#039;&#039;&#039;&#039;&#039;{c}&#039;&#039;&#039;&#039;&#039; — пересчёт кластерных центров и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; значений полученных кластерных центров).]]&lt;br /&gt;
[[File:HardCMeans2.PNG|thumb|400px|center|Рисунок 2. Подробное описание работы блока  &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039;. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (1 значение центра кластера на каждую из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; соответствующих вершин графа и значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;), &#039;&#039;&#039;&#039;&#039;d1,...,dC&#039;&#039;&#039;&#039;&#039; — прямое вычисление  расстояния до кластерных центров, &#039;&#039;&#039;&#039;&#039;max&#039;&#039;&#039;&#039;&#039; — вычисление максимума двух чисел (с сохранением соответствующего максимуму кластерного индекса) и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (индекс кластерного центра, расположенного ближе всего к точке &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;, и соответствующее расстояние).]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
Для выполнения одной итерации алгоритма C средних необходимо выполнить параллельно ряд вычислений для каждого из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; элементов:&lt;br /&gt;
&lt;br /&gt;
1. Вычисление &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; расстояний между элементом и кластерными центрами.&lt;br /&gt;
&lt;br /&gt;
2. Выполнение &amp;lt;math&amp;gt;(c - 1)&amp;lt;/math&amp;gt; сравнений для определения минимального.&lt;br /&gt;
&lt;br /&gt;
3. Определение значений столбца матрицы принадлежности &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, соответствующей элементу.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; &lt;br /&gt;
*&amp;lt;math&amp;gt;\{u_k\}_{k=1}^{n} \subset \mathbb{R}^m&amp;lt;/math&amp;gt; — исходный набор векторов;&lt;br /&gt;
*&amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; — желаемое количество кластеров (&amp;lt;math&amp;gt;2 \leqslant c \leqslant n&amp;lt;/math&amp;gt;);&lt;br /&gt;
* &#039;&#039;(опционально)&#039;&#039; &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; — пороговая точность работы алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;mn+1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
*&amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; — рядовая матрица из пространства &amp;lt;math&amp;gt;\mathbb{R}^{c \times n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;cn&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Назначение:&#039;&#039;&#039; кластеризация больших наборов числовых данных.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Достоинства:&#039;&#039;&#039;&lt;br /&gt;
* лёгкость реализации;&lt;br /&gt;
* вычислительная простота.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Недостатки:&#039;&#039;&#039;&lt;br /&gt;
* нет гарантии, что итеративный процесс сойдётся к оптимальному решению;&lt;br /&gt;
* производительность существенно зависит от выбора начальных кластерных центров.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Юрий Комаров</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=8006</id>
		<title>Участник:Светлана Лукьяненко/Строгий алгоритм С средних (Hard C-Means, HCM)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=8006"/>
		<updated>2016-10-14T19:19:05Z</updated>

		<summary type="html">&lt;p&gt;Юрий Комаров: /* Вычислительное ядро алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Строгий алгоритм С средних (Hard C-Means,HCM)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;-&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;-&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mn+1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;cn&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы описания: [[Участник:Светлана_Лукьяненко|Лукьяненко Светлана]], [[Участник:Юрий_Комаров|Комаров Юрий]].&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Строгий алгоритм C средних&#039;&#039;&#039; (&#039;&#039;&#039;&#039;&#039;Hard C-Means&#039;&#039;&#039;&#039;&#039;; &#039;&#039;Jang, Sun and Mizutani, 1997&#039;&#039;) позволяет распределить большие наборы числовых данных по кластерам в многомерном пространстве&amp;lt;ref&amp;gt;Jan Jantzen «Neurofuzzy Modelling». Электронное издание.&amp;lt;/ref&amp;gt;. Алгоритм является управляемым, так как для работы с ним требуется задание одного параметра — числа кластеров, на которое необходимо разделить данные. &lt;br /&gt;
Входными данными для алгоритма являются набор векторов и количество кластеров, также может задаваться пороговое значение величины объектной функции, по достижении которого расчёт прекращается. Выходными данными для алгоритма является рядовая матрица, отображающая принадлежность исходных элементов построенным кластерам, и центры построенных кластеров.&lt;br /&gt;
&lt;br /&gt;
Первым шагом выполнения алгоритма является инициализация центров кластеров случайными значениями. Дальнейшие шаги алгоритма выполняются итеративно до тех пор, пока объектная функция не станет меньше порогового значения или же значение объектной функции не будет минимально отличаться от полученного на предыдущей итерации. На каждой итерации вычислений выполняются следующие действия:&lt;br /&gt;
&lt;br /&gt;
# Расчёт рядовой матрицы, сопоставляющей каждый вектор с ближайшим кластерным центром.&lt;br /&gt;
# Расчёт объектной функции; проверка условий остановки и завершение расчёта в случае их выполнения.&lt;br /&gt;
# Пересчёт кластерных центров.&lt;br /&gt;
&lt;br /&gt;
Так как алгоритм является итеративным и зависит от начальных значений кластерных центров, он может не сходиться к локальному минимуму.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
==== Входные и выходные данные ====&lt;br /&gt;
На вход подаётся набор векторов &amp;lt;math&amp;gt;\{u_k\}_{k=1}^{n}&amp;lt;/math&amp;gt; пространства &amp;lt;math&amp;gt;\mathbb{R}^m&amp;lt;/math&amp;gt; и количество кластеров &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Конечным результатом работы алгоритма являются построенная рядовая матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, содержащая информацию о принадлежности элементов кластерам:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ij} = \begin{cases}&lt;br /&gt;
1, &amp;amp; u_j \in C_i, \\&lt;br /&gt;
0, &amp;amp; \text{otherwise},&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; подразумевается &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый построенный кластер, и набор &amp;lt;math&amp;gt;\{c_i\}_{i=1}^{C}&amp;lt;/math&amp;gt; центров этих кластеров.&lt;br /&gt;
&lt;br /&gt;
==== Описание алгоритма ====&lt;br /&gt;
Алгоритм состоит из 5 последовательных шагов.&amp;lt;ref&amp;gt; Нейский И.М. Классификация и сравнение методов кластеризации.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 1&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация кластерных центров&#039;&#039;&#039; &amp;lt;math&amp;gt;c_i \, (i=1,2,\ldots,C)&amp;lt;/math&amp;gt; может происходить за счёт случайного выбора необходимого числа точек из входного набора либо путём явного указания.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 2&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вычисление рядовой матрицы&#039;&#039;&#039; &amp;lt;math&amp;gt;M = \|m_{ik}\|&amp;lt;/math&amp;gt;, элементы которой задаются следующими выражениями (&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; — количество элементов во входном наборе данных):&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ik} = \begin{cases}&lt;br /&gt;
1, &amp;amp; \|u_k-c_i\|^2 \leqslant \|u_k-c_j\|^2 \;\; \text{for all } i \neq j; \;\; (i=1,2,\ldots,C; \; k = 1,2,\ldots,N)\\&lt;br /&gt;
0, &amp;amp; \text{otherwise}.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;!-- При этом, как легко видеть, матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; обладает следующими свойствами:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\sum\limits_{i=1}^C m_{ij} = 1, \;\; \sum\limits_{i=1}^C\sum\limits_{j=1}^K m_{ij} = K.&lt;br /&gt;
&amp;lt;/math&amp;gt; --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Будем говорить, что &amp;lt;math&amp;gt;u_k \in C_i&amp;lt;/math&amp;gt;, если &amp;lt;math&amp;gt;m_{ik} = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 3&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Расчёт объектной функции:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^C J_i = \sum\limits_{i=1}^C \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right)&lt;br /&gt;
.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На этом шаге происходит &#039;&#039;&#039;&amp;lt;u&amp;gt;остановка и выход из цикла&amp;lt;/u&amp;gt;&#039;&#039;&#039;, если полученное значение ниже пороговой величины &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; или полученное значение не сильно отличается от значений, полученных на предыдущих циклах.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 4&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Пересчёт кластерных центров&#039;&#039;&#039; выполняется в соответствии со следующим уравнением:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;|C_i|&amp;lt;/math&amp;gt; подразумевается количество элементов в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом кластере.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 5&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Переход по циклу&#039;&#039;&#039; на шаг 2.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма составляют вычисления квадратов нормы расстояния от каждого из векторов исходной выборки до промежуточных кластерных центров &amp;lt;math&amp;gt;\|u_k-c_i\|^2&amp;lt;/math&amp;gt;. На каждой итерации алгоритма происходит расчёт &amp;lt;math&amp;gt;CN&amp;lt;/math&amp;gt; таких расстояний.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Основной операцией, выполняемой в алгоритме, как сказано выше, является операция нахождения квадратов расстояний между векторами данных и кластерными центрами. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
d_{ki} = \|u_k-c_i\|^2&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также на шаге вычисления объектной функции производится множественное суммирование полученных расстояний:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^c J_i = \sum\limits_{i=1}^c \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right),&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
а на шаге расчета кластерных центров происходит суммирование векторов:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Реализация последовательного алгоритма состоит в итеративном повторении блока, описанного далее в форме псевдокода, до тех пор, пока не будет достигнута желаемая точность.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;&lt;br /&gt;
J = 0;&lt;br /&gt;
M = zeros(n,C);&lt;br /&gt;
for i = 1 to n //go through every element&lt;br /&gt;
   d_min = MAXINT;&lt;br /&gt;
   j_min = 1;&lt;br /&gt;
   for j = 1 to C //deside which claster does element belong to&lt;br /&gt;
      d_ij  = sq_norm(u[i] - c[j]);&lt;br /&gt;
      if d_ij &amp;lt; d_min&lt;br /&gt;
         d_min = d_ij;&lt;br /&gt;
         j_min = j;&lt;br /&gt;
   //generation of output data&lt;br /&gt;
   J += d_min; &lt;br /&gt;
   M[i,j_min] = 1;&lt;br /&gt;
   c_new[j] += u[i];&lt;br /&gt;
   c_newCount[k]++;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
На каждой итерации алгоритма требуется выполнение:&lt;br /&gt;
* &amp;lt;math&amp;gt;nC&amp;lt;/math&amp;gt; операций вычисления квадрата нормы разности элементов;&lt;br /&gt;
* &amp;lt;math&amp;gt;nC&amp;lt;/math&amp;gt; операций сравнения (вычитаний);&lt;br /&gt;
* &amp;lt;math&amp;gt;3n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
&lt;br /&gt;
Преполагая, что операция вычисления нормы вектора предполагает выполнение &amp;lt;math&amp;gt;2m&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания и &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; операций возведения в квадрат (умножений), получаем, что реализация алгоритма требует выполнения&lt;br /&gt;
* &amp;lt;math&amp;gt;2mnC&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания;&lt;br /&gt;
* &amp;lt;math&amp;gt;(3+(m+1)C)n&amp;lt;/math&amp;gt; операций умножения&lt;br /&gt;
на каждой итерации цикла.&lt;br /&gt;
&lt;br /&gt;
Ожидая, что предельная точность будет достигнута не более, чем за &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; итераций (что соответствует объёму исходной выборки), получаем итоговую сложность последовательной реализации алгоритма &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
[[File:HardCMeans1.png|thumb|800px|center|Рисунок 1. Информационный граф алгоритма. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (&amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; стартовых значений кластерных центров и 1 значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; на каждую вершину графа), &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039; — вычисление минимального расстояния до кластерных центров (подробнее см. рисунок 2), &#039;&#039;&#039;&#039;&#039;M&#039;&#039;&#039;&#039;&#039; — запись единички в соответствующую строчку матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, &#039;&#039;&#039;&#039;&#039;J&#039;&#039;&#039;&#039;&#039; — вычисление объектной функции по результатам полученных вычислений, &#039;&#039;&#039;&#039;&#039;if&#039;&#039;&#039;&#039;&#039; — проверка условия достижения заданной точности, &#039;&#039;&#039;&#039;&#039;{c}&#039;&#039;&#039;&#039;&#039; — пересчёт кластерных центров и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; значений полученных кластерных центров).]]&lt;br /&gt;
[[File:HardCMeans2.PNG|thumb|400px|center|Рисунок 2. Подробное описание работы блока  &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039;. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (1 значение центра кластера на каждую из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; соответствующих вершин графа и значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;), &#039;&#039;&#039;&#039;&#039;d1,...,dC&#039;&#039;&#039;&#039;&#039; — прямое вычисление  расстояния до кластерных центров, &#039;&#039;&#039;&#039;&#039;max&#039;&#039;&#039;&#039;&#039; — вычисление максимума двух чисел (с сохранением соответствующего максимуму кластерного индекса) и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (индекс кластерного центра, расположенного ближе всего к точке &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;, и соответствующее расстояние).]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
Для выполнения одной итерации алгоритма C средних необходимо выполнить параллельно ряд вычислений для каждого из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; элементов:&lt;br /&gt;
&lt;br /&gt;
1. Вычисление &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; расстояний между элементом и кластерными центрами.&lt;br /&gt;
&lt;br /&gt;
2. Выполнение &amp;lt;math&amp;gt;(c - 1)&amp;lt;/math&amp;gt; сравнений для определения минимального.&lt;br /&gt;
&lt;br /&gt;
3. Определение значений столбца матрицы принадлежности &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, соответствующей элементу.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; &lt;br /&gt;
*&amp;lt;math&amp;gt;\{u_k\}_{k=1}^{n} \subset \mathbb{R}^m&amp;lt;/math&amp;gt; — исходный набор векторов;&lt;br /&gt;
*&amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; — желаемое количество кластеров (&amp;lt;math&amp;gt;2 \leqslant c \leqslant n&amp;lt;/math&amp;gt;);&lt;br /&gt;
* &#039;&#039;(опционально)&#039;&#039; &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; — пороговая точность работы алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;mn+1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
*&amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; — рядовая матрица из пространства &amp;lt;math&amp;gt;\mathbb{R}^{c \times n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;cn&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Назначение:&#039;&#039;&#039; кластеризация больших наборов числовых данных.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Достоинства:&#039;&#039;&#039;&lt;br /&gt;
* лёгкость реализации;&lt;br /&gt;
* вычислительная простота.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Недостатки:&#039;&#039;&#039;&lt;br /&gt;
* нет гарантии, что итеративный процесс сойдётся к оптимальному решению;&lt;br /&gt;
* производительность существенно зависит от выбора начальных кластерных центров.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Юрий Комаров</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=8005</id>
		<title>Участник:Светлана Лукьяненко/Строгий алгоритм С средних (Hard C-Means, HCM)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=8005"/>
		<updated>2016-10-14T19:18:48Z</updated>

		<summary type="html">&lt;p&gt;Юрий Комаров: /* Описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Строгий алгоритм С средних (Hard C-Means,HCM)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;-&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;-&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mn+1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;cn&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы описания: [[Участник:Светлана_Лукьяненко|Лукьяненко Светлана]], [[Участник:Юрий_Комаров|Комаров Юрий]].&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Строгий алгоритм C средних&#039;&#039;&#039; (&#039;&#039;&#039;&#039;&#039;Hard C-Means&#039;&#039;&#039;&#039;&#039;; &#039;&#039;Jang, Sun and Mizutani, 1997&#039;&#039;) позволяет распределить большие наборы числовых данных по кластерам в многомерном пространстве&amp;lt;ref&amp;gt;Jan Jantzen «Neurofuzzy Modelling». Электронное издание.&amp;lt;/ref&amp;gt;. Алгоритм является управляемым, так как для работы с ним требуется задание одного параметра — числа кластеров, на которое необходимо разделить данные. &lt;br /&gt;
Входными данными для алгоритма являются набор векторов и количество кластеров, также может задаваться пороговое значение величины объектной функции, по достижении которого расчёт прекращается. Выходными данными для алгоритма является рядовая матрица, отображающая принадлежность исходных элементов построенным кластерам, и центры построенных кластеров.&lt;br /&gt;
&lt;br /&gt;
Первым шагом выполнения алгоритма является инициализация центров кластеров случайными значениями. Дальнейшие шаги алгоритма выполняются итеративно до тех пор, пока объектная функция не станет меньше порогового значения или же значение объектной функции не будет минимально отличаться от полученного на предыдущей итерации. На каждой итерации вычислений выполняются следующие действия:&lt;br /&gt;
&lt;br /&gt;
# Расчёт рядовой матрицы, сопоставляющей каждый вектор с ближайшим кластерным центром.&lt;br /&gt;
# Расчёт объектной функции; проверка условий остановки и завершение расчёта в случае их выполнения.&lt;br /&gt;
# Пересчёт кластерных центров.&lt;br /&gt;
&lt;br /&gt;
Так как алгоритм является итеративным и зависит от начальных значений кластерных центров, он может не сходиться к локальному минимуму.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
==== Входные и выходные данные ====&lt;br /&gt;
На вход подаётся набор векторов &amp;lt;math&amp;gt;\{u_k\}_{k=1}^{n}&amp;lt;/math&amp;gt; пространства &amp;lt;math&amp;gt;\mathbb{R}^m&amp;lt;/math&amp;gt; и количество кластеров &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Конечным результатом работы алгоритма являются построенная рядовая матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, содержащая информацию о принадлежности элементов кластерам:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ij} = \begin{cases}&lt;br /&gt;
1, &amp;amp; u_j \in C_i, \\&lt;br /&gt;
0, &amp;amp; \text{otherwise},&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; подразумевается &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый построенный кластер, и набор &amp;lt;math&amp;gt;\{c_i\}_{i=1}^{C}&amp;lt;/math&amp;gt; центров этих кластеров.&lt;br /&gt;
&lt;br /&gt;
==== Описание алгоритма ====&lt;br /&gt;
Алгоритм состоит из 5 последовательных шагов.&amp;lt;ref&amp;gt; Нейский И.М. Классификация и сравнение методов кластеризации.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 1&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация кластерных центров&#039;&#039;&#039; &amp;lt;math&amp;gt;c_i \, (i=1,2,\ldots,C)&amp;lt;/math&amp;gt; может происходить за счёт случайного выбора необходимого числа точек из входного набора либо путём явного указания.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 2&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вычисление рядовой матрицы&#039;&#039;&#039; &amp;lt;math&amp;gt;M = \|m_{ik}\|&amp;lt;/math&amp;gt;, элементы которой задаются следующими выражениями (&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; — количество элементов во входном наборе данных):&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ik} = \begin{cases}&lt;br /&gt;
1, &amp;amp; \|u_k-c_i\|^2 \leqslant \|u_k-c_j\|^2 \;\; \text{for all } i \neq j; \;\; (i=1,2,\ldots,C; \; k = 1,2,\ldots,N)\\&lt;br /&gt;
0, &amp;amp; \text{otherwise}.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;!-- При этом, как легко видеть, матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; обладает следующими свойствами:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\sum\limits_{i=1}^C m_{ij} = 1, \;\; \sum\limits_{i=1}^C\sum\limits_{j=1}^K m_{ij} = K.&lt;br /&gt;
&amp;lt;/math&amp;gt; --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Будем говорить, что &amp;lt;math&amp;gt;u_k \in C_i&amp;lt;/math&amp;gt;, если &amp;lt;math&amp;gt;m_{ik} = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 3&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Расчёт объектной функции:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^C J_i = \sum\limits_{i=1}^C \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right)&lt;br /&gt;
.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На этом шаге происходит &#039;&#039;&#039;&amp;lt;u&amp;gt;остановка и выход из цикла&amp;lt;/u&amp;gt;&#039;&#039;&#039;, если полученное значение ниже пороговой величины &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; или полученное значение не сильно отличается от значений, полученных на предыдущих циклах.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 4&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Пересчёт кластерных центров&#039;&#039;&#039; выполняется в соответствии со следующим уравнением:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;|C_i|&amp;lt;/math&amp;gt; подразумевается количество элементов в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом кластере.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 5&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Переход по циклу&#039;&#039;&#039; на шаг 2.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма составляют вычисления квадратов нормы расстояния от каждого из векторов исходной выборки до промежуточных кластерных центров &amp;lt;math&amp;gt;\|u_k-c_i\|^2&amp;lt;/math&amp;gt;. На каждой итерации алгоритма происходит расчёт &amp;lt;math&amp;gt;cn&amp;lt;/math&amp;gt; таких расстояний.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Основной операцией, выполняемой в алгоритме, как сказано выше, является операция нахождения квадратов расстояний между векторами данных и кластерными центрами. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
d_{ki} = \|u_k-c_i\|^2&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также на шаге вычисления объектной функции производится множественное суммирование полученных расстояний:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^c J_i = \sum\limits_{i=1}^c \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right),&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
а на шаге расчета кластерных центров происходит суммирование векторов:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Реализация последовательного алгоритма состоит в итеративном повторении блока, описанного далее в форме псевдокода, до тех пор, пока не будет достигнута желаемая точность.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;&lt;br /&gt;
J = 0;&lt;br /&gt;
M = zeros(n,C);&lt;br /&gt;
for i = 1 to n //go through every element&lt;br /&gt;
   d_min = MAXINT;&lt;br /&gt;
   j_min = 1;&lt;br /&gt;
   for j = 1 to C //deside which claster does element belong to&lt;br /&gt;
      d_ij  = sq_norm(u[i] - c[j]);&lt;br /&gt;
      if d_ij &amp;lt; d_min&lt;br /&gt;
         d_min = d_ij;&lt;br /&gt;
         j_min = j;&lt;br /&gt;
   //generation of output data&lt;br /&gt;
   J += d_min; &lt;br /&gt;
   M[i,j_min] = 1;&lt;br /&gt;
   c_new[j] += u[i];&lt;br /&gt;
   c_newCount[k]++;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
На каждой итерации алгоритма требуется выполнение:&lt;br /&gt;
* &amp;lt;math&amp;gt;nC&amp;lt;/math&amp;gt; операций вычисления квадрата нормы разности элементов;&lt;br /&gt;
* &amp;lt;math&amp;gt;nC&amp;lt;/math&amp;gt; операций сравнения (вычитаний);&lt;br /&gt;
* &amp;lt;math&amp;gt;3n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
&lt;br /&gt;
Преполагая, что операция вычисления нормы вектора предполагает выполнение &amp;lt;math&amp;gt;2m&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания и &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; операций возведения в квадрат (умножений), получаем, что реализация алгоритма требует выполнения&lt;br /&gt;
* &amp;lt;math&amp;gt;2mnC&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания;&lt;br /&gt;
* &amp;lt;math&amp;gt;(3+(m+1)C)n&amp;lt;/math&amp;gt; операций умножения&lt;br /&gt;
на каждой итерации цикла.&lt;br /&gt;
&lt;br /&gt;
Ожидая, что предельная точность будет достигнута не более, чем за &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; итераций (что соответствует объёму исходной выборки), получаем итоговую сложность последовательной реализации алгоритма &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
[[File:HardCMeans1.png|thumb|800px|center|Рисунок 1. Информационный граф алгоритма. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (&amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; стартовых значений кластерных центров и 1 значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; на каждую вершину графа), &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039; — вычисление минимального расстояния до кластерных центров (подробнее см. рисунок 2), &#039;&#039;&#039;&#039;&#039;M&#039;&#039;&#039;&#039;&#039; — запись единички в соответствующую строчку матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, &#039;&#039;&#039;&#039;&#039;J&#039;&#039;&#039;&#039;&#039; — вычисление объектной функции по результатам полученных вычислений, &#039;&#039;&#039;&#039;&#039;if&#039;&#039;&#039;&#039;&#039; — проверка условия достижения заданной точности, &#039;&#039;&#039;&#039;&#039;{c}&#039;&#039;&#039;&#039;&#039; — пересчёт кластерных центров и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; значений полученных кластерных центров).]]&lt;br /&gt;
[[File:HardCMeans2.PNG|thumb|400px|center|Рисунок 2. Подробное описание работы блока  &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039;. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (1 значение центра кластера на каждую из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; соответствующих вершин графа и значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;), &#039;&#039;&#039;&#039;&#039;d1,...,dC&#039;&#039;&#039;&#039;&#039; — прямое вычисление  расстояния до кластерных центров, &#039;&#039;&#039;&#039;&#039;max&#039;&#039;&#039;&#039;&#039; — вычисление максимума двух чисел (с сохранением соответствующего максимуму кластерного индекса) и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (индекс кластерного центра, расположенного ближе всего к точке &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;, и соответствующее расстояние).]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
Для выполнения одной итерации алгоритма C средних необходимо выполнить параллельно ряд вычислений для каждого из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; элементов:&lt;br /&gt;
&lt;br /&gt;
1. Вычисление &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; расстояний между элементом и кластерными центрами.&lt;br /&gt;
&lt;br /&gt;
2. Выполнение &amp;lt;math&amp;gt;(c - 1)&amp;lt;/math&amp;gt; сравнений для определения минимального.&lt;br /&gt;
&lt;br /&gt;
3. Определение значений столбца матрицы принадлежности &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, соответствующей элементу.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; &lt;br /&gt;
*&amp;lt;math&amp;gt;\{u_k\}_{k=1}^{n} \subset \mathbb{R}^m&amp;lt;/math&amp;gt; — исходный набор векторов;&lt;br /&gt;
*&amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; — желаемое количество кластеров (&amp;lt;math&amp;gt;2 \leqslant c \leqslant n&amp;lt;/math&amp;gt;);&lt;br /&gt;
* &#039;&#039;(опционально)&#039;&#039; &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; — пороговая точность работы алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;mn+1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
*&amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; — рядовая матрица из пространства &amp;lt;math&amp;gt;\mathbb{R}^{c \times n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;cn&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Назначение:&#039;&#039;&#039; кластеризация больших наборов числовых данных.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Достоинства:&#039;&#039;&#039;&lt;br /&gt;
* лёгкость реализации;&lt;br /&gt;
* вычислительная простота.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Недостатки:&#039;&#039;&#039;&lt;br /&gt;
* нет гарантии, что итеративный процесс сойдётся к оптимальному решению;&lt;br /&gt;
* производительность существенно зависит от выбора начальных кластерных центров.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Юрий Комаров</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=7998</id>
		<title>Участник:Светлана Лукьяненко/Строгий алгоритм С средних (Hard C-Means, HCM)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=7998"/>
		<updated>2016-10-14T19:16:59Z</updated>

		<summary type="html">&lt;p&gt;Юрий Комаров: /* Описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Строгий алгоритм С средних (Hard C-Means,HCM)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;-&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;-&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mn+1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;cn&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы описания: [[Участник:Светлана_Лукьяненко|Лукьяненко Светлана]], [[Участник:Юрий_Комаров|Комаров Юрий]].&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Строгий алгоритм C средних&#039;&#039;&#039; (&#039;&#039;&#039;&#039;&#039;Hard C-Means&#039;&#039;&#039;&#039;&#039;; &#039;&#039;Jang, Sun and Mizutani, 1997&#039;&#039;) позволяет распределить большие наборы числовых данных по кластерам в многомерном пространстве&amp;lt;ref&amp;gt;Jan Jantzen «Neurofuzzy Modelling». Электронное издание.&amp;lt;/ref&amp;gt;. Алгоритм является управляемым, так как для работы с ним требуется задание одного параметра — числа кластеров, на которое необходимо разделить данные. &lt;br /&gt;
Входными данными для алгоритма являются набор векторов и количество кластеров, также может задаваться пороговое значение величины объектной функции, по достижении которого расчёт прекращается. Выходными данными для алгоритма является рядовая матрица, отображающая принадлежность исходных элементов построенным кластерам, и центры построенных кластеров.&lt;br /&gt;
&lt;br /&gt;
Первым шагом выполнения алгоритма является инициализация центров кластеров случайными значениями. Дальнейшие шаги алгоритма выполняются итеративно до тех пор, пока объектная функция не станет меньше порогового значения или же значение объектной функции не будет минимально отличаться от полученного на предыдущей итерации. На каждой итерации вычислений выполняются следующие действия:&lt;br /&gt;
&lt;br /&gt;
# Расчёт рядовой матрицы, сопоставляющей каждый вектор с ближайшим кластерным центром.&lt;br /&gt;
# Расчёт объектной функции; проверка условий остановки и завершение расчёта в случае их выполнения.&lt;br /&gt;
# Пересчёт кластерных центров.&lt;br /&gt;
&lt;br /&gt;
Так как алгоритм является итеративным и зависит от начальных значений кластерных центров, он может не сходиться к локальному минимуму.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
==== Входные и выходные данные ====&lt;br /&gt;
На вход подаётся набор векторов &amp;lt;math&amp;gt;\{u_k\}_{k=1}^{n}&amp;lt;/math&amp;gt; пространства &amp;lt;math&amp;gt;\mathbb{R}^m&amp;lt;/math&amp;gt; и количество кластеров &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Конечным результатом работы алгоритма являются построенная рядовая матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, содержащая информацию о принадлежности элементов кластерам:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ij} = \begin{cases}&lt;br /&gt;
1, &amp;amp; u_j \in C_i, \\&lt;br /&gt;
0, &amp;amp; \text{otherwise},&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; подразумевается &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый построенный кластер, и набор &amp;lt;math&amp;gt;\{c_i\}_{i=1}^{C}&amp;lt;/math&amp;gt; центров этих кластеров.&lt;br /&gt;
&lt;br /&gt;
==== Описание алгоритма ====&lt;br /&gt;
Алгоритм состоит из 5 последовательных шагов.&amp;lt;ref&amp;gt; Нейский И.М. Классификация и сравнение методов кластеризации.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 1&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация кластерных центров&#039;&#039;&#039; &amp;lt;math&amp;gt;c_i \, (i=1,2,\ldots,C)&amp;lt;/math&amp;gt; может происходить за счёт случайного выбора необходимого числа точек из входного набора либо путём явного указания.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 2&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вычисление рядовой матрицы&#039;&#039;&#039; &amp;lt;math&amp;gt;M = \|m_{ik}\|&amp;lt;/math&amp;gt;, элементы которой задаются следующими выражениями (&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; — количество элементов во входном наборе данных):&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ik} = \begin{cases}&lt;br /&gt;
1, &amp;amp; \|u_k-c_i\|^2 \leqslant \|u_k-c_j\|^2 \;\; \text{for all } i \neq j; \;\; (i=1,2,\ldots,C; \; k = 1,2,\ldots,N)\\&lt;br /&gt;
0, &amp;amp; \text{otherwise}.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;!-- При этом, как легко видеть, матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; обладает следующими свойствами:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\sum\limits_{i=1}^C m_{ij} = 1, \;\; \sum\limits_{i=1}^C\sum\limits_{j=1}^K m_{ij} = K.&lt;br /&gt;
&amp;lt;/math&amp;gt; --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Будем говорить, что &amp;lt;math&amp;gt;u_k \in C_i&amp;lt;/math&amp;gt;, если &amp;lt;math&amp;gt;m_{ik} = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 3&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Расчёт объектной функции:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^C J_i = \sum\limits_{i=1}^C \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right)&lt;br /&gt;
.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На этом шаге происходит остановка и выход из цикла, если полученное значение ниже пороговой величины &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; или полученное значение не сильно отличается от значений, полученных на предыдущих циклах.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 4&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Пересчёт кластерных центров&#039;&#039;&#039; выполняется в соответствии со следующим уравнением:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;|C_i|&amp;lt;/math&amp;gt; подразумевается количество элементов в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом кластере.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 5&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Переход по циклу&#039;&#039;&#039; на шаг 2.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма составляют вычисления квадратов нормы расстояния от каждого из векторов исходной выборки до промежуточных кластерных центров &amp;lt;math&amp;gt;\|u_k-c_i\|^2&amp;lt;/math&amp;gt;. На каждой итерации алгоритма происходит расчёт &amp;lt;math&amp;gt;cn&amp;lt;/math&amp;gt; таких расстояний.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Основной операцией, выполняемой в алгоритме, как сказано выше, является операция нахождения квадратов расстояний между векторами данных и кластерными центрами. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
d_{ki} = \|u_k-c_i\|^2&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также на шаге вычисления объектной функции производится множественное суммирование полученных расстояний:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^c J_i = \sum\limits_{i=1}^c \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right),&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
а на шаге расчета кластерных центров происходит суммирование векторов:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Реализация последовательного алгоритма состоит в итеративном повторении блока, описанного далее в форме псевдокода, до тех пор, пока не будет достигнута желаемая точность.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;&lt;br /&gt;
J = 0;&lt;br /&gt;
M = zeros(n,C);&lt;br /&gt;
for i = 1 to n //go through every element&lt;br /&gt;
   d_min = MAXINT;&lt;br /&gt;
   j_min = 1;&lt;br /&gt;
   for j = 1 to C //deside which claster does element belong to&lt;br /&gt;
      d_ij  = sq_norm(u[i] - c[j]);&lt;br /&gt;
      if d_ij &amp;lt; d_min&lt;br /&gt;
         d_min = d_ij;&lt;br /&gt;
         j_min = j;&lt;br /&gt;
   //generation of output data&lt;br /&gt;
   J += d_min; &lt;br /&gt;
   M[i,j_min] = 1;&lt;br /&gt;
   c_new[j] += u[i];&lt;br /&gt;
   c_newCount[k]++;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
На каждой итерации алгоритма требуется выполнение:&lt;br /&gt;
* &amp;lt;math&amp;gt;nC&amp;lt;/math&amp;gt; операций вычисления квадрата нормы разности элементов;&lt;br /&gt;
* &amp;lt;math&amp;gt;nC&amp;lt;/math&amp;gt; операций сравнения (вычитаний);&lt;br /&gt;
* &amp;lt;math&amp;gt;3n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
&lt;br /&gt;
Преполагая, что операция вычисления нормы вектора предполагает выполнение &amp;lt;math&amp;gt;2m&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания и &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; операций возведения в квадрат (умножений), получаем, что реализация алгоритма требует выполнения&lt;br /&gt;
* &amp;lt;math&amp;gt;2mnC&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания;&lt;br /&gt;
* &amp;lt;math&amp;gt;(3+(m+1)C)n&amp;lt;/math&amp;gt; операций умножения&lt;br /&gt;
на каждой итерации цикла.&lt;br /&gt;
&lt;br /&gt;
Ожидая, что предельная точность будет достигнута не более, чем за &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; итераций (что соответствует объёму исходной выборки), получаем итоговую сложность последовательной реализации алгоритма &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
[[File:HardCMeans1.png|thumb|800px|center|Рисунок 1. Информационный граф алгоритма. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (&amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; стартовых значений кластерных центров и 1 значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; на каждую вершину графа), &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039; — вычисление минимального расстояния до кластерных центров (подробнее см. рисунок 2), &#039;&#039;&#039;&#039;&#039;M&#039;&#039;&#039;&#039;&#039; — запись единички в соответствующую строчку матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, &#039;&#039;&#039;&#039;&#039;J&#039;&#039;&#039;&#039;&#039; — вычисление объектной функции по результатам полученных вычислений, &#039;&#039;&#039;&#039;&#039;if&#039;&#039;&#039;&#039;&#039; — проверка условия достижения заданной точности, &#039;&#039;&#039;&#039;&#039;{c}&#039;&#039;&#039;&#039;&#039; — пересчёт кластерных центров и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; значений полученных кластерных центров).]]&lt;br /&gt;
[[File:HardCMeans2.PNG|thumb|400px|center|Рисунок 2. Подробное описание работы блока  &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039;. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (1 значение центра кластера на каждую из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; соответствующих вершин графа и значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;), &#039;&#039;&#039;&#039;&#039;d1,...,dC&#039;&#039;&#039;&#039;&#039; — прямое вычисление  расстояния до кластерных центров, &#039;&#039;&#039;&#039;&#039;max&#039;&#039;&#039;&#039;&#039; — вычисление максимума двух чисел (с сохранением соответствующего максимуму кластерного индекса) и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (индекс кластерного центра, расположенного ближе всего к точке &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;, и соответствующее расстояние).]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
Для выполнения одной итерации алгоритма C средних необходимо выполнить параллельно ряд вычислений для каждого из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; элементов:&lt;br /&gt;
&lt;br /&gt;
1. Вычисление &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; расстояний между элементом и кластерными центрами.&lt;br /&gt;
&lt;br /&gt;
2. Выполнение &amp;lt;math&amp;gt;(c - 1)&amp;lt;/math&amp;gt; сравнений для определения минимального.&lt;br /&gt;
&lt;br /&gt;
3. Определение значений столбца матрицы принадлежности &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, соответствующей элементу.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; &lt;br /&gt;
*&amp;lt;math&amp;gt;\{u_k\}_{k=1}^{n} \subset \mathbb{R}^m&amp;lt;/math&amp;gt; — исходный набор векторов;&lt;br /&gt;
*&amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; — желаемое количество кластеров (&amp;lt;math&amp;gt;2 \leqslant c \leqslant n&amp;lt;/math&amp;gt;);&lt;br /&gt;
* &#039;&#039;(опционально)&#039;&#039; &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; — пороговая точность работы алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;mn+1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
*&amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; — рядовая матрица из пространства &amp;lt;math&amp;gt;\mathbb{R}^{c \times n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;cn&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Назначение:&#039;&#039;&#039; кластеризация больших наборов числовых данных.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Достоинства:&#039;&#039;&#039;&lt;br /&gt;
* лёгкость реализации;&lt;br /&gt;
* вычислительная простота.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Недостатки:&#039;&#039;&#039;&lt;br /&gt;
* нет гарантии, что итеративный процесс сойдётся к оптимальному решению;&lt;br /&gt;
* производительность существенно зависит от выбора начальных кластерных центров.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Юрий Комаров</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=7992</id>
		<title>Участник:Светлана Лукьяненко/Строгий алгоритм С средних (Hard C-Means, HCM)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=7992"/>
		<updated>2016-10-14T19:15:10Z</updated>

		<summary type="html">&lt;p&gt;Юрий Комаров: /* Описание алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Строгий алгоритм С средних (Hard C-Means,HCM)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;-&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;-&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mn+1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;cn&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы описания: [[Участник:Светлана_Лукьяненко|Лукьяненко Светлана]], [[Участник:Юрий_Комаров|Комаров Юрий]].&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Строгий алгоритм C средних&#039;&#039;&#039; (&#039;&#039;&#039;&#039;&#039;Hard C-Means&#039;&#039;&#039;&#039;&#039;; &#039;&#039;Jang, Sun and Mizutani, 1997&#039;&#039;) позволяет распределить большие наборы числовых данных по кластерам в многомерном пространстве&amp;lt;ref&amp;gt;Jan Jantzen «Neurofuzzy Modelling». Электронное издание.&amp;lt;/ref&amp;gt;. Алгоритм является управляемым, так как для работы с ним требуется задание одного параметра — числа кластеров, на которое необходимо разделить данные. &lt;br /&gt;
Входными данными для алгоритма являются набор векторов и количество кластеров, также может задаваться пороговое значение величины объектной функции, по достижении которого расчёт прекращается. Выходными данными для алгоритма является рядовая матрица, отображающая принадлежность исходных элементов построенным кластерам, и центры построенных кластеров.&lt;br /&gt;
&lt;br /&gt;
Первым шагом выполнения алгоритма является инициализация центров кластеров случайными значениями. Дальнейшие шаги алгоритма выполняются итеративно до тех пор, пока объектная функция не станет меньше порогового значения или же значение объектной функции не будет минимально отличаться от полученного на предыдущей итерации. На каждой итерации вычислений выполняются следующие действия:&lt;br /&gt;
&lt;br /&gt;
# Расчёт рядовой матрицы, сопоставляющей каждый вектор с ближайшим кластерным центром.&lt;br /&gt;
# Расчёт объектной функции; проверка условий остановки и завершение расчёта в случае их выполнения.&lt;br /&gt;
# Пересчёт кластерных центров.&lt;br /&gt;
&lt;br /&gt;
Так как алгоритм является итеративным и зависит от начальных значений кластерных центров, он может не сходиться к локальному минимуму.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
==== Входные и выходные данные ====&lt;br /&gt;
На вход подаётся набор векторов &amp;lt;math&amp;gt;\{u_k\}_{k=1}^{n}&amp;lt;/math&amp;gt; пространства &amp;lt;math&amp;gt;\mathbb{R}^m&amp;lt;/math&amp;gt; и количество кластеров &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Конечным результатом работы алгоритма являются построенная рядовая матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, содержащая информацию о принадлежности элементов кластерам:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ij} = \begin{cases}&lt;br /&gt;
1, &amp;amp; u_j \in C_i, \\&lt;br /&gt;
0, &amp;amp; \text{otherwise},&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; подразумевается &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый построенный кластер, и набор &amp;lt;math&amp;gt;\{c_i\}_{i=1}^{C}&amp;lt;/math&amp;gt; центров этих кластеров.&lt;br /&gt;
&lt;br /&gt;
==== Описание алгоритма ====&lt;br /&gt;
Алгоритм состоит из 5 последовательных шагов.&amp;lt;ref&amp;gt; Нейский И.М. Классификация и сравнение методов кластеризации.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 1&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация кластерных центров&#039;&#039;&#039; &amp;lt;math&amp;gt;c_i \, (i=1,2,\ldots,C)&amp;lt;/math&amp;gt; может происходить за счёт случайного выбора необходимого числа точек из входного набора либо путём явного указания.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 2&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вычисление рядовой матрицы&#039;&#039;&#039; &amp;lt;math&amp;gt;M = \|m_{ik}\|&amp;lt;/math&amp;gt;, элементы которой задаются следующими выражениями (&amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; — количество элементов во входном наборе данных):&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ik} = \begin{cases}&lt;br /&gt;
1, &amp;amp; \|u_k-c_i\|^2 \leqslant \|u_k-c_j\|^2 \;\; \text{for all } i \neq j; \;\; (i=1,2,\ldots,c, \; k = 1,2,\ldots,n)\\&lt;br /&gt;
0, &amp;amp; \text{otherwise}.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;!-- При этом, как легко видеть, матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; обладает следующими свойствами:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\sum\limits_{i=1}^c m_{ij} = 1, \;\; \sum\limits_{i=1}^c\sum\limits_{j=1}^K m_{ij} = K.&lt;br /&gt;
&amp;lt;/math&amp;gt; --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Будем говорить, что &amp;lt;math&amp;gt;u_k \in C_i&amp;lt;/math&amp;gt;, если &amp;lt;math&amp;gt;m_{ik} = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 3&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Расчёт объектной функции:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^c J_i = \sum\limits_{i=1}^c \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right)&lt;br /&gt;
.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На этом шаге происходит остановка и выход из цикла, если полученное значение ниже пороговой величины &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; или полученное значение не сильно отличается от значений, полученных на предыдущих циклах.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 4&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Пересчёт кластерных центров&#039;&#039;&#039; выполняется в соответствии со следующим уравнением:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;|C_i|&amp;lt;/math&amp;gt; подразумевается количество элементов в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом кластере.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 5&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Переход по циклу&#039;&#039;&#039; на шаг 2.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма составляют вычисления квадратов нормы расстояния от каждого из векторов исходной выборки до промежуточных кластерных центров &amp;lt;math&amp;gt;\|u_k-c_i\|^2&amp;lt;/math&amp;gt;. На каждой итерации алгоритма происходит расчёт &amp;lt;math&amp;gt;cn&amp;lt;/math&amp;gt; таких расстояний.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Основной операцией, выполняемой в алгоритме, как сказано выше, является операция нахождения квадратов расстояний между векторами данных и кластерными центрами. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
d_{ki} = \|u_k-c_i\|^2&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также на шаге вычисления объектной функции производится множественное суммирование полученных расстояний:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^c J_i = \sum\limits_{i=1}^c \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right),&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
а на шаге расчета кластерных центров происходит суммирование векторов:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Реализация последовательного алгоритма состоит в итеративном повторении блока, описанного далее в форме псевдокода, до тех пор, пока не будет достигнута желаемая точность.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;&lt;br /&gt;
J = 0;&lt;br /&gt;
M = zeros(n,C);&lt;br /&gt;
for i = 1 to n //go through every element&lt;br /&gt;
   d_min = MAXINT;&lt;br /&gt;
   j_min = 1;&lt;br /&gt;
   for j = 1 to C //deside which claster does element belong to&lt;br /&gt;
      d_ij  = sq_norm(u[i] - c[j]);&lt;br /&gt;
      if d_ij &amp;lt; d_min&lt;br /&gt;
         d_min = d_ij;&lt;br /&gt;
         j_min = j;&lt;br /&gt;
   //generation of output data&lt;br /&gt;
   J += d_min; &lt;br /&gt;
   M[i,j_min] = 1;&lt;br /&gt;
   c_new[j] += u[i];&lt;br /&gt;
   c_newCount[k]++;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
На каждой итерации алгоритма требуется выполнение:&lt;br /&gt;
* &amp;lt;math&amp;gt;nC&amp;lt;/math&amp;gt; операций вычисления квадрата нормы разности элементов;&lt;br /&gt;
* &amp;lt;math&amp;gt;nC&amp;lt;/math&amp;gt; операций сравнения (вычитаний);&lt;br /&gt;
* &amp;lt;math&amp;gt;3n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
&lt;br /&gt;
Преполагая, что операция вычисления нормы вектора предполагает выполнение &amp;lt;math&amp;gt;2m&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания и &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; операций возведения в квадрат (умножений), получаем, что реализация алгоритма требует выполнения&lt;br /&gt;
* &amp;lt;math&amp;gt;2mnC&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания;&lt;br /&gt;
* &amp;lt;math&amp;gt;(3+(m+1)C)n&amp;lt;/math&amp;gt; операций умножения&lt;br /&gt;
на каждой итерации цикла.&lt;br /&gt;
&lt;br /&gt;
Ожидая, что предельная точность будет достигнута не более, чем за &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; итераций (что соответствует объёму исходной выборки), получаем итоговую сложность последовательной реализации алгоритма &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
[[File:HardCMeans1.png|thumb|800px|center|Рисунок 1. Информационный граф алгоритма. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (&amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; стартовых значений кластерных центров и 1 значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; на каждую вершину графа), &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039; — вычисление минимального расстояния до кластерных центров (подробнее см. рисунок 2), &#039;&#039;&#039;&#039;&#039;M&#039;&#039;&#039;&#039;&#039; — запись единички в соответствующую строчку матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, &#039;&#039;&#039;&#039;&#039;J&#039;&#039;&#039;&#039;&#039; — вычисление объектной функции по результатам полученных вычислений, &#039;&#039;&#039;&#039;&#039;if&#039;&#039;&#039;&#039;&#039; — проверка условия достижения заданной точности, &#039;&#039;&#039;&#039;&#039;{c}&#039;&#039;&#039;&#039;&#039; — пересчёт кластерных центров и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; значений полученных кластерных центров).]]&lt;br /&gt;
[[File:HardCMeans2.PNG|thumb|400px|center|Рисунок 2. Подробное описание работы блока  &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039;. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (1 значение центра кластера на каждую из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; соответствующих вершин графа и значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;), &#039;&#039;&#039;&#039;&#039;d1,...,dC&#039;&#039;&#039;&#039;&#039; — прямое вычисление  расстояния до кластерных центров, &#039;&#039;&#039;&#039;&#039;max&#039;&#039;&#039;&#039;&#039; — вычисление максимума двух чисел (с сохранением соответствующего максимуму кластерного индекса) и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (индекс кластерного центра, расположенного ближе всего к точке &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;, и соответствующее расстояние).]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
Для выполнения одной итерации алгоритма C средних необходимо выполнить параллельно ряд вычислений для каждого из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; элементов:&lt;br /&gt;
&lt;br /&gt;
1. Вычисление &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; расстояний между элементом и кластерными центрами.&lt;br /&gt;
&lt;br /&gt;
2. Выполнение &amp;lt;math&amp;gt;(c - 1)&amp;lt;/math&amp;gt; сравнений для определения минимального.&lt;br /&gt;
&lt;br /&gt;
3. Определение значений столбца матрицы принадлежности &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, соответствующей элементу.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; &lt;br /&gt;
*&amp;lt;math&amp;gt;\{u_k\}_{k=1}^{n} \subset \mathbb{R}^m&amp;lt;/math&amp;gt; — исходный набор векторов;&lt;br /&gt;
*&amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; — желаемое количество кластеров (&amp;lt;math&amp;gt;2 \leqslant c \leqslant n&amp;lt;/math&amp;gt;);&lt;br /&gt;
* &#039;&#039;(опционально)&#039;&#039; &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; — пороговая точность работы алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;mn+1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
*&amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; — рядовая матрица из пространства &amp;lt;math&amp;gt;\mathbb{R}^{c \times n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;cn&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Назначение:&#039;&#039;&#039; кластеризация больших наборов числовых данных.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Достоинства:&#039;&#039;&#039;&lt;br /&gt;
* лёгкость реализации;&lt;br /&gt;
* вычислительная простота.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Недостатки:&#039;&#039;&#039;&lt;br /&gt;
* нет гарантии, что итеративный процесс сойдётся к оптимальному решению;&lt;br /&gt;
* производительность существенно зависит от выбора начальных кластерных центров.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Юрий Комаров</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=7991</id>
		<title>Участник:Светлана Лукьяненко/Строгий алгоритм С средних (Hard C-Means, HCM)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9B%D1%83%D0%BA%D1%8C%D1%8F%D0%BD%D0%B5%D0%BD%D0%BA%D0%BE/%D0%A1%D1%82%D1%80%D0%BE%D0%B3%D0%B8%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%A1_%D1%81%D1%80%D0%B5%D0%B4%D0%BD%D0%B8%D1%85_(Hard_C-Means,_HCM)&amp;diff=7991"/>
		<updated>2016-10-14T19:14:50Z</updated>

		<summary type="html">&lt;p&gt;Юрий Комаров: /* Входные и выходные данные */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Строгий алгоритм С средних (Hard C-Means,HCM)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;-&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;-&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;mn+1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;cn&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы описания: [[Участник:Светлана_Лукьяненко|Лукьяненко Светлана]], [[Участник:Юрий_Комаров|Комаров Юрий]].&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Строгий алгоритм C средних&#039;&#039;&#039; (&#039;&#039;&#039;&#039;&#039;Hard C-Means&#039;&#039;&#039;&#039;&#039;; &#039;&#039;Jang, Sun and Mizutani, 1997&#039;&#039;) позволяет распределить большие наборы числовых данных по кластерам в многомерном пространстве&amp;lt;ref&amp;gt;Jan Jantzen «Neurofuzzy Modelling». Электронное издание.&amp;lt;/ref&amp;gt;. Алгоритм является управляемым, так как для работы с ним требуется задание одного параметра — числа кластеров, на которое необходимо разделить данные. &lt;br /&gt;
Входными данными для алгоритма являются набор векторов и количество кластеров, также может задаваться пороговое значение величины объектной функции, по достижении которого расчёт прекращается. Выходными данными для алгоритма является рядовая матрица, отображающая принадлежность исходных элементов построенным кластерам, и центры построенных кластеров.&lt;br /&gt;
&lt;br /&gt;
Первым шагом выполнения алгоритма является инициализация центров кластеров случайными значениями. Дальнейшие шаги алгоритма выполняются итеративно до тех пор, пока объектная функция не станет меньше порогового значения или же значение объектной функции не будет минимально отличаться от полученного на предыдущей итерации. На каждой итерации вычислений выполняются следующие действия:&lt;br /&gt;
&lt;br /&gt;
# Расчёт рядовой матрицы, сопоставляющей каждый вектор с ближайшим кластерным центром.&lt;br /&gt;
# Расчёт объектной функции; проверка условий остановки и завершение расчёта в случае их выполнения.&lt;br /&gt;
# Пересчёт кластерных центров.&lt;br /&gt;
&lt;br /&gt;
Так как алгоритм является итеративным и зависит от начальных значений кластерных центров, он может не сходиться к локальному минимуму.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
==== Входные и выходные данные ====&lt;br /&gt;
На вход подаётся набор векторов &amp;lt;math&amp;gt;\{u_k\}_{k=1}^{n}&amp;lt;/math&amp;gt; пространства &amp;lt;math&amp;gt;\mathbb{R}^m&amp;lt;/math&amp;gt; и количество кластеров &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Конечным результатом работы алгоритма являются построенная рядовая матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, содержащая информацию о принадлежности элементов кластерам:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ij} = \begin{cases}&lt;br /&gt;
1, &amp;amp; u_j \in C_i, \\&lt;br /&gt;
0, &amp;amp; \text{otherwise},&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; подразумевается &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый построенный кластер, и набор &amp;lt;math&amp;gt;\{c_i\}_{i=1}^{C}&amp;lt;/math&amp;gt; центров этих кластеров.&lt;br /&gt;
&lt;br /&gt;
==== Описание алгоритма ====&lt;br /&gt;
Алгоритм состоит из 5 последовательных шагов.&amp;lt;ref&amp;gt; Нейский И.М. Классификация и сравнение методов кластеризации.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 1&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация кластерных центров&#039;&#039;&#039; &amp;lt;math&amp;gt;c_i \, (i=1,2,\ldots,c)&amp;lt;/math&amp;gt; может происходить за счёт случайного выбора необходимого числа точек из входного набора либо путём явного указания.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 2&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вычисление рядовой матрицы&#039;&#039;&#039; &amp;lt;math&amp;gt;M = \|m_{ik}\|&amp;lt;/math&amp;gt;, элементы которой задаются следующими выражениями (&amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; — количество элементов во входном наборе данных):&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
m_{ik} = \begin{cases}&lt;br /&gt;
1, &amp;amp; \|u_k-c_i\|^2 \leqslant \|u_k-c_j\|^2 \;\; \text{for all } i \neq j; \;\; (i=1,2,\ldots,c, \; k = 1,2,\ldots,n)\\&lt;br /&gt;
0, &amp;amp; \text{otherwise}.&lt;br /&gt;
\end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&amp;lt;!-- При этом, как легко видеть, матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; обладает следующими свойствами:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\sum\limits_{i=1}^c m_{ij} = 1, \;\; \sum\limits_{i=1}^c\sum\limits_{j=1}^K m_{ij} = K.&lt;br /&gt;
&amp;lt;/math&amp;gt; --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Будем говорить, что &amp;lt;math&amp;gt;u_k \in C_i&amp;lt;/math&amp;gt;, если &amp;lt;math&amp;gt;m_{ik} = 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 3&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Расчёт объектной функции:&#039;&#039;&#039;&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^c J_i = \sum\limits_{i=1}^c \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right)&lt;br /&gt;
.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На этом шаге происходит остановка и выход из цикла, если полученное значение ниже пороговой величины &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; или полученное значение не сильно отличается от значений, полученных на предыдущих циклах.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 4&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Пересчёт кластерных центров&#039;&#039;&#039; выполняется в соответствии со следующим уравнением:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k,&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где под &amp;lt;math&amp;gt;|C_i|&amp;lt;/math&amp;gt; подразумевается количество элементов в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом кластере.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;u&amp;gt;Шаг 5&amp;lt;/u&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Переход по циклу&#039;&#039;&#039; на шаг 2.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма составляют вычисления квадратов нормы расстояния от каждого из векторов исходной выборки до промежуточных кластерных центров &amp;lt;math&amp;gt;\|u_k-c_i\|^2&amp;lt;/math&amp;gt;. На каждой итерации алгоритма происходит расчёт &amp;lt;math&amp;gt;cn&amp;lt;/math&amp;gt; таких расстояний.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Основной операцией, выполняемой в алгоритме, как сказано выше, является операция нахождения квадратов расстояний между векторами данных и кластерными центрами. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
d_{ki} = \|u_k-c_i\|^2&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также на шаге вычисления объектной функции производится множественное суммирование полученных расстояний:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
J = \sum\limits_{i=1}^c J_i = \sum\limits_{i=1}^c \left( \sum\limits_{k:\, u_k \in C_i} \|u_k -c_i \|^2 \right),&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
а на шаге расчета кластерных центров происходит суммирование векторов:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
c_i = \frac{1}{|C_i|} \sum\limits_{k:\, u_k \in C_i} u_k.&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Реализация последовательного алгоритма состоит в итеративном повторении блока, описанного далее в форме псевдокода, до тех пор, пока не будет достигнута желаемая точность.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;pascal&amp;quot;&amp;gt;&lt;br /&gt;
J = 0;&lt;br /&gt;
M = zeros(n,C);&lt;br /&gt;
for i = 1 to n //go through every element&lt;br /&gt;
   d_min = MAXINT;&lt;br /&gt;
   j_min = 1;&lt;br /&gt;
   for j = 1 to C //deside which claster does element belong to&lt;br /&gt;
      d_ij  = sq_norm(u[i] - c[j]);&lt;br /&gt;
      if d_ij &amp;lt; d_min&lt;br /&gt;
         d_min = d_ij;&lt;br /&gt;
         j_min = j;&lt;br /&gt;
   //generation of output data&lt;br /&gt;
   J += d_min; &lt;br /&gt;
   M[i,j_min] = 1;&lt;br /&gt;
   c_new[j] += u[i];&lt;br /&gt;
   c_newCount[k]++;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
На каждой итерации алгоритма требуется выполнение:&lt;br /&gt;
* &amp;lt;math&amp;gt;nC&amp;lt;/math&amp;gt; операций вычисления квадрата нормы разности элементов;&lt;br /&gt;
* &amp;lt;math&amp;gt;nC&amp;lt;/math&amp;gt; операций сравнения (вычитаний);&lt;br /&gt;
* &amp;lt;math&amp;gt;3n&amp;lt;/math&amp;gt; операций сложения.&lt;br /&gt;
&lt;br /&gt;
Преполагая, что операция вычисления нормы вектора предполагает выполнение &amp;lt;math&amp;gt;2m&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания и &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; операций возведения в квадрат (умножений), получаем, что реализация алгоритма требует выполнения&lt;br /&gt;
* &amp;lt;math&amp;gt;2mnC&amp;lt;/math&amp;gt; арифметических операций сложения и вычитания;&lt;br /&gt;
* &amp;lt;math&amp;gt;(3+(m+1)C)n&amp;lt;/math&amp;gt; операций умножения&lt;br /&gt;
на каждой итерации цикла.&lt;br /&gt;
&lt;br /&gt;
Ожидая, что предельная точность будет достигнута не более, чем за &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; итераций (что соответствует объёму исходной выборки), получаем итоговую сложность последовательной реализации алгоритма &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
[[File:HardCMeans1.png|thumb|800px|center|Рисунок 1. Информационный граф алгоритма. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (&amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; стартовых значений кластерных центров и 1 значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt; на каждую вершину графа), &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039; — вычисление минимального расстояния до кластерных центров (подробнее см. рисунок 2), &#039;&#039;&#039;&#039;&#039;M&#039;&#039;&#039;&#039;&#039; — запись единички в соответствующую строчку матрицы &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, &#039;&#039;&#039;&#039;&#039;J&#039;&#039;&#039;&#039;&#039; — вычисление объектной функции по результатам полученных вычислений, &#039;&#039;&#039;&#039;&#039;if&#039;&#039;&#039;&#039;&#039; — проверка условия достижения заданной точности, &#039;&#039;&#039;&#039;&#039;{c}&#039;&#039;&#039;&#039;&#039; — пересчёт кластерных центров и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (матрица &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; значений полученных кластерных центров).]]&lt;br /&gt;
[[File:HardCMeans2.PNG|thumb|400px|center|Рисунок 2. Подробное описание работы блока  &#039;&#039;&#039;&#039;&#039;d&#039;&#039;&#039;&#039;&#039;. Здесь &#039;&#039;&#039;&#039;&#039;in&#039;&#039;&#039;&#039;&#039; — ввод входных данных (1 значение центра кластера на каждую из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; соответствующих вершин графа и значение &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;), &#039;&#039;&#039;&#039;&#039;d1,...,dC&#039;&#039;&#039;&#039;&#039; — прямое вычисление  расстояния до кластерных центров, &#039;&#039;&#039;&#039;&#039;max&#039;&#039;&#039;&#039;&#039; — вычисление максимума двух чисел (с сохранением соответствующего максимуму кластерного индекса) и &#039;&#039;&#039;&#039;&#039;out&#039;&#039;&#039;&#039;&#039; — вывод полученных данных (индекс кластерного центра, расположенного ближе всего к точке &amp;lt;math&amp;gt;u_i&amp;lt;/math&amp;gt;, и соответствующее расстояние).]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
Для выполнения одной итерации алгоритма C средних необходимо выполнить параллельно ряд вычислений для каждого из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; элементов:&lt;br /&gt;
&lt;br /&gt;
1. Вычисление &amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; расстояний между элементом и кластерными центрами.&lt;br /&gt;
&lt;br /&gt;
2. Выполнение &amp;lt;math&amp;gt;(c - 1)&amp;lt;/math&amp;gt; сравнений для определения минимального.&lt;br /&gt;
&lt;br /&gt;
3. Определение значений столбца матрицы принадлежности &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;, соответствующей элементу.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; &lt;br /&gt;
*&amp;lt;math&amp;gt;\{u_k\}_{k=1}^{n} \subset \mathbb{R}^m&amp;lt;/math&amp;gt; — исходный набор векторов;&lt;br /&gt;
*&amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; — желаемое количество кластеров (&amp;lt;math&amp;gt;2 \leqslant c \leqslant n&amp;lt;/math&amp;gt;);&lt;br /&gt;
* &#039;&#039;(опционально)&#039;&#039; &amp;lt;math&amp;gt;\varepsilon_{tr}&amp;lt;/math&amp;gt; — пороговая точность работы алгоритма.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;mn+1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
*&amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; — рядовая матрица из пространства &amp;lt;math&amp;gt;\mathbb{R}^{c \times n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;cn&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Назначение:&#039;&#039;&#039; кластеризация больших наборов числовых данных.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Достоинства:&#039;&#039;&#039;&lt;br /&gt;
* лёгкость реализации;&lt;br /&gt;
* вычислительная простота.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Недостатки:&#039;&#039;&#039;&lt;br /&gt;
* нет гарантии, что итеративный процесс сойдётся к оптимальному решению;&lt;br /&gt;
* производительность существенно зависит от выбора начальных кластерных центров.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Юрий Комаров</name></author>
	</entry>
</feed>