<?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=Algoman</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=Algoman"/>
	<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/Algoman"/>
	<updated>2026-10-22T16:10:34Z</updated>
	<subtitle>Вклад</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9F%D0%B5%D1%80%D0%B5%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BB%D0%BE%D1%82%D0%BD%D1%8B%D1%85_%D0%BD%D0%B5%D0%BE%D1%81%D0%BE%D0%B1%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86_(%D0%BF%D0%BE%D1%81%D0%BB%D0%B5%D0%B4%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D1%8B%D0%B9_%D0%B2%D0%B5%D1%89%D0%B5%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D0%B9_%D0%B2%D0%B0%D1%80%D0%B8%D0%B0%D0%BD%D1%82)&amp;diff=22550</id>
		<title>Перемножение плотных неособенных матриц (последовательный вещественный вариант)</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9F%D0%B5%D1%80%D0%B5%D0%BC%D0%BD%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BF%D0%BB%D0%BE%D1%82%D0%BD%D1%8B%D1%85_%D0%BD%D0%B5%D0%BE%D1%81%D0%BE%D0%B1%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86_(%D0%BF%D0%BE%D1%81%D0%BB%D0%B5%D0%B4%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D1%8B%D0%B9_%D0%B2%D0%B5%D1%89%D0%B5%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D1%8B%D0%B9_%D0%B2%D0%B0%D1%80%D0%B8%D0%B0%D0%BD%D1%82)&amp;diff=22550"/>
		<updated>2017-04-20T14:24:50Z</updated>

		<summary type="html">&lt;p&gt;Algoman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Основные авторы описания: [[Участник:Frolov|А.В.Фролов]], [[Участник:VadimVV|Вад.В.Воеводин]] ([[#Описание локальности данных и вычислений|раздел 2.2]]), [[Участник:Teplov|А.М.Теплов]] (раздел [[#Масштабируемость алгоритма и его реализации|2.4]])&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Перемножение матриц&#039;&#039;&#039; - одна из базовых задач в алгоритмах линейной алгебры, широко применяется в большом количестве разных методов.&lt;br /&gt;
Здесь мы рассмотрим умножение &amp;lt;math&amp;gt;C = AB&amp;lt;/math&amp;gt;&amp;amp;nbsp; плотных неособенных матриц (последовательный вещественный вариант), то есть тот вариант, где никак не используются ни специальный вид матрицы, ни ассоциативные свойства операции сложения&amp;lt;ref&amp;gt;В.В.Воеводин, Ю.А.Кузнецов. Матрицы и вычисления. М.: Наука, 1984.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Исходные данные: плотная матрица &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;a_{ij}&amp;lt;/math&amp;gt;), плотная матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;b_{ij}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные: плотная матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;c_{ij}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Формулы метода:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
c_{ij} = \sum_{k = 1}^{n} a_{ik} b_{kj}, \quad i \in [1, m], \quad i \in [1, l].&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Существует также блочная версия метода, однако в данном описании разобран только точечный метод.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро перемножения плотных неособенных матриц можно составить из множественных (всего их &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt;) вычислений умножения матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; на столбцы матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;, или (при более детальном рассмотрении), из множественных (всего их &amp;lt;math&amp;gt;ml&amp;lt;/math&amp;gt;) скалярных произведений строк матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; на столбцы матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\sum_{k = 1}^{n} a_{ik} b_{kj}&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
в режиме накопления или без него, в зависимости от требований задачи.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Как уже записано в [[#Вычислительное ядро алгоритма|описании ядра алгоритма]], основную часть умножения матриц составляют множественные (всего &amp;lt;math&amp;gt;ml&amp;lt;/math&amp;gt;) вычисления скалярных произведений строк матрицы &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; на столбцы матрицы &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\sum_{k = 1}^{n} a_{ik} b_{kj}&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
в режиме накопления или без него.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для всех &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; от &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;  и для всех &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; от &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; выполняются&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;c_{ij} = \sum_{k = 1}^{n} a_{ik} b_{kj}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Особо отметим, что вычисления сумм вида &amp;lt;math&amp;gt;\sum_{k = 1}^{n} a_{ik} b_{kj}&amp;lt;/math&amp;gt; производят в режиме накопления прибавлением к текущему (временному) значению вычисляемого элемента матрицы &amp;lt;math&amp;gt;c_{ij}&amp;lt;/math&amp;gt; произведений &amp;lt;math&amp;gt;a_{ik} b_{kj}&amp;lt;/math&amp;gt; для &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; от &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, &#039;&#039;&#039;c возрастанием&#039;&#039;&#039; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;, вначале все элементы инициализируются нулями. При суммировании &amp;quot;по убыванию&amp;quot; общая схема принципиально не отличается и потому нами не рассматривается. Другие порядки выполнения суммирования приводят к изменению параллельных свойств алгоритма и будут рассматриваться нами в отдельных описаниях.&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для умножения двух квадратных матриц порядка &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; (т.е. при &amp;lt;math&amp;gt;m=n=l&amp;lt;/math&amp;gt;) в последовательном (наиболее быстром) варианте требуется:&lt;br /&gt;
	&lt;br /&gt;
* по &amp;lt;math&amp;gt;n^3&amp;lt;/math&amp;gt; умножений и сложений.&lt;br /&gt;
&lt;br /&gt;
Для умножения матрицы размером &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; строк на &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; столбцов на матрицу размером &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; строк на &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; столбцов в последовательном (наиболее быстром) варианте требуется:&lt;br /&gt;
&lt;br /&gt;
* по &amp;lt;math&amp;gt;mnl&amp;lt;/math&amp;gt; умножений и сложений.&lt;br /&gt;
 &lt;br /&gt;
При этом использование режима накопления требует совершения умножений и сложений в режиме двойной точности (или использования функции вроде DPROD в Фортране), что ещё больше увеличивает затраты во времени, требуемом для выполнения умножения матриц.&lt;br /&gt;
&lt;br /&gt;
При классификации по последовательной сложности, таким образом, алгоритм умножения матриц относится к алгоритмам &#039;&#039;с кубической сложностью&#039;&#039; (в случае неквадратных матриц - с &#039;&#039;трилинейной&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
&lt;br /&gt;
Опишем [[глоссарий#Граф алгоритма|граф алгоритма]] как аналитически, так и в виде рисунка.&lt;br /&gt;
&lt;br /&gt;
Граф алгоритма умножения плотных матриц состоит из одной группы вершин, расположенной в целочисленных узлах трёхмерной области, соответствующая ей операция  &amp;lt;math&amp;gt;a+bc&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Естественно введённые координаты области таковы: &lt;br /&gt;
* &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; — меняется в диапазоне от &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, принимая все целочисленные значения;&lt;br /&gt;
* &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; — меняется в диапазоне от &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt;, принимая все целочисленные значения;&lt;br /&gt;
* &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; — меняется в диапазоне от &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, принимая все целочисленные значения.&lt;br /&gt;
&lt;br /&gt;
Аргументы операции следующие:&lt;br /&gt;
*&amp;lt;math&amp;gt;a&amp;lt;/math&amp;gt;:&lt;br /&gt;
** при &amp;lt;math&amp;gt;k = 1&amp;lt;/math&amp;gt; константа &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt;; &lt;br /&gt;
** при &amp;lt;math&amp;gt;k &amp;gt; 1&amp;lt;/math&amp;gt; — результат срабатывания операции, соответствующей вершине с координатами &amp;lt;math&amp;gt;i, j, k-1&amp;lt;/math&amp;gt;;&lt;br /&gt;
*&amp;lt;math&amp;gt;b&amp;lt;/math&amp;gt; — элемент &#039;&#039;входных данных&#039;&#039;, а именно  &amp;lt;math&amp;gt;a_{ik}&amp;lt;/math&amp;gt;;&lt;br /&gt;
*&amp;lt;math&amp;gt;c&amp;lt;/math&amp;gt; - элемент &#039;&#039;входных данных&#039;&#039; &amp;lt;math&amp;gt;b_{kj}&amp;lt;/math&amp;gt;; &lt;br /&gt;
&lt;br /&gt;
Результат срабатывания операции является:&lt;br /&gt;
* при &amp;lt;math&amp;gt;k &amp;lt; n&amp;lt;/math&amp;gt; - &#039;&#039;промежуточным данным&#039;&#039; алгоритма;&lt;br /&gt;
* при &amp;lt;math&amp;gt;k = n&amp;lt;/math&amp;gt; - выходным данным &amp;lt;math&amp;gt;c_{ij}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[file:Dense mtrx product.png|thumb|center|800px|Рисунок 1. Умножение плотных матриц с отображением выходных данных]]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
Интерактивное изображение графа алгоритма без входных и выходных данных для случая перемножения двух квадратных матриц порядка 3 и 4&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
{{#widget:Algoviewer&lt;br /&gt;
|url=mat_mul/mat_mul_3/Algo_view_matrix3.html&lt;br /&gt;
|width=1300&lt;br /&gt;
|height=800&lt;br /&gt;
|border=1&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{#widget:Algoviewer&lt;br /&gt;
|url=mat_mul/mat_mul_4/Algo_view_matrix4.html&lt;br /&gt;
|width=1300&lt;br /&gt;
|height=800&lt;br /&gt;
|border=1&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для алгоритма умножения квадратных матриц порядка n в параллельном варианте требуется последовательно выполнить следующие ярусы:&lt;br /&gt;
&lt;br /&gt;
* по &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; ярусов умножений и сложений (в каждом из ярусов — &amp;lt;math&amp;gt;n^2&amp;lt;/math&amp;gt; операций).&lt;br /&gt;
&lt;br /&gt;
Для умножения матрицы размером &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; строк на &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; столбцов на матрицу размером &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; строк на &amp;lt;math&amp;gt;l&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;ml&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;&#039; (для матриц общего вида).&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: матрица &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;a_{ij}&amp;lt;/math&amp;gt;), матрица &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;b_{ij}&amp;lt;/math&amp;gt;)).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;mn+nl&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: матрица &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;c_{ij}&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;ml&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; (отношение кубической или трилинейной к линейной). &lt;br /&gt;
&lt;br /&gt;
При этом вычислительная мощность алгоритма умножения матриц, как отношение числа операций к суммарному объему входных и выходных данных – &#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;
&amp;lt;source lang=&amp;quot;fortran&amp;quot;&amp;gt;&lt;br /&gt;
         &lt;br /&gt;
	DO  I = 1, M&lt;br /&gt;
        DO  J = 1, L&lt;br /&gt;
		S = 0.&lt;br /&gt;
		DO  K = 1, N&lt;br /&gt;
			S = S + DPROD(A(I,K), B(K,J))&lt;br /&gt;
		END DO	&lt;br /&gt;
	        C(I, J) = S&lt;br /&gt;
        END DO&lt;br /&gt;
	END DO&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
При этом для реализации режима накопления переменная &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; должна быть двойной точности.&lt;br /&gt;
&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
&lt;br /&gt;
[[file:matrmult 1.PNG|thumb|center|700px|Рисунок 2. Профили обращений для 6 вариантов перемножения матриц]]&lt;br /&gt;
&lt;br /&gt;
На рис.2 представлены 6 профилей обращений для различных вариантов классического перемножения матриц (в зависимости от выбранного порядка циклов). На каждом профиле хорошо выделяются фрагменты профилей для 3-х массивов, используемых в программе. При этом порядок обращений к разным массивам во всех 6 вариантах один и тот же; т.е. взаимодействие между  массивами везде устроен одинаково. В этом случае отличия в локальности задаются внутренним строением фрагментов профиля для каждого массива в отдельности.&lt;br /&gt;
&lt;br /&gt;
Исходя из исходного кода, можно увидеть, что всего встречается 6 разных видов фрагментов для отдельных массивов (эти виды выделены на рис.2 зеленым). Стоит сделать два уточнения: 1) профиль для результирующего массива С всегда в 2 раза больше, поскольку к элементам этого массива всегда происходят по два обращения подряд; 2) если во внутреннем цикле используется элементы массива, то обращение к этому элементу выносится за пределы внутреннего цикла (в цикле используется скалярная переменная вместо него).&lt;br /&gt;
&lt;br /&gt;
Также заранее отметим, что рисунки по профилям получаются следующим образом: строится рисунок по общему профилю, после чего из него оставляется только часть для рассматриваемого массива. Доля обращений к одному массиву может меняться, поэтому и частота обращений на каждом рисунке может в значительной степени отличаться.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим подробнее каждый из данных 6 фрагментов на примере массива С.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Фрагмент 1.&#039;&#039;&#039; На рис.3 показано начало фрагмента 1 (здесь и далее начало фрагмента соответствует выделенной оранжевой области на рис.2). Можно увидеть, что данный фрагмент устроен достаточно просто: выполняется перебор некоторого блока элементов массива, затем данный перебор циклически повторяется. После этого происходит переход к следующему блоку элементов массива, и выполняется тот же перебор в цикле.&lt;br /&gt;
&lt;br /&gt;
Если рассмотреть фрагмент более подробно (рис.4), можно увидеть, что каждый перебор является на самом деле последовательным перебором, при этом к каждому элементу происходит обращение дважды.&lt;br /&gt;
&lt;br /&gt;
В результате можно сделать вывод, что фрагмент 1 обладает высокой пространственной локальностью (из-за последовательного перебора и последовательной смены блоков перебора), а также высокой временно́й локальностью (из-за двойного обращения к элементам, а также сгруппированности всех обращений к одному элементу в рамках одного блока перебора). &lt;br /&gt;
&lt;br /&gt;
[[file:matrmult 2.PNG|thumb|center|700px|Рисунок 3. Начало фрагмента 1]]&lt;br /&gt;
[[file:matrmult 3.PNG|thumb|center|700px|Рисунок 4. Начало фрагмента 1, первые 3 итерации]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Фрагмент 2.&#039;&#039;&#039; На рис.5 представлено начало фрагмента 2. Видно, что данный фрагмент также представляет собой перебор элементов массива в цикле, однако в данном случае на каждой итерации цикла перебираются сразу все элементы массива, а не только элементы одного блока. При более подробном рассмотрении итерации (рис.6) видно, что здесь также происходит именно последовательный перебор, и также к каждому элементу обращение происходит дважды (поскольку это массив С).&lt;br /&gt;
&lt;br /&gt;
[[file:matrmult 4.PNG|thumb|center|700px|Рисунок 5. Начало фрагмента 2]]&lt;br /&gt;
[[file:matrmult 5.PNG|thumb|center|700px|Рисунок 6. Начало фрагмента 2, часть первой итерации]]&lt;br /&gt;
&lt;br /&gt;
Такой фрагмент также обладает высокой пространственной локальностью, однако временна́я локальность несколько ниже, чем во фрагменте 1. Это связано с тем, что на каждой итерации цикла перебираются все элементы массива, а не только отдельный блок, т.е. повторные обращения происходят реже.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Фрагмент 3.&#039;&#039;&#039; Начало данного фрагмента представлено на рисунке 7. Данный профиль является последовательным перебором всех элементов массива, однако более подробное рассмотрение показывает, что к каждому элементу происходит обращение дважды, при этом между обращениями происходит достаточно много других обращений. Это связано с указанным ранее замечанием касательно вынесения повторяющегося обращения за предел внутреннего цикла.&lt;br /&gt;
&lt;br /&gt;
[[file:matrmult 6.PNG|thumb|center|700px|Рисунок 7. Начало фрагмента 3]]&lt;br /&gt;
[[file:matrmult 7.PNG|thumb|center|700px|Рисунок 8. Начало фрагмента 3, первые несколько обращений]]&lt;br /&gt;
&lt;br /&gt;
Такой фрагмент также обладает высокой пространственной локальностью, однако очень низкой временно́й, поскольку к каждому элементу обращение происходит только два раза.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Фрагмент 4.&#039;&#039;&#039; По началу фрагмента 4 видно, что профиль снова состоит из перебора всех элементов массива, однако на этот раз перебор не последовательный, а с некоторым шагом. Также можно заметить, что на каждой новой итерации перебор с шагом начинается с элемента, индекс которого немного больше, чем на предыдущей итерации. В данном случае нет нужды рассматривать профиль более подробно, поскольку из данного рисунка можно получить всю необходимую информацию.&lt;br /&gt;
&lt;br /&gt;
По сравнению с предыдущим фрагментом, данный профиль обладает более низкой пространственной локальностью, поскольку перебор элементов идет с шагом, и также очень низкой временно́й локальностью, поскольку на каждой итерации происходят обращения к новым элементам.&lt;br /&gt;
&lt;br /&gt;
[[file:matrmult 8.PNG|thumb|center|700px|Рисунок 9. Начало фрагмента 4]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Фрагмент 5.&#039;&#039;&#039; В отличие от предыдущих фрагментов, исходя из визуализации начала данного фрагмента (рис.9), сложно сделать выводы относительно структуры обращения в память. Однако более подробное рассмотрение (рис.10) показывает, что данный профиль практически идентичен профилю предыдущего фрагмента. Более того, фрагмент 5 на самом деле состоит из итерационно повторяющихся фрагментов 4.&lt;br /&gt;
&lt;br /&gt;
[[file:matrmult 9.PNG|thumb|center|700px|Рисунок 10. Начало фрагмента 5]]&lt;br /&gt;
[[file:matrmult 10.PNG|thumb|center|700px|Рисунок 11. Начало фрагмента 5, первые несколько итераций]]&lt;br /&gt;
&lt;br /&gt;
Данный фрагмент обладает по сравнению с фрагментом 4 практически такой же пространственной локальностью, однако более высокой временной локальностью. Причина в обоих случаях одна – в данном случае тот же набор обращений повторяется несколько раз.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Фрагмент 6.&#039;&#039;&#039; Данный фрагмент, представленный на рис.12 и рис.13, так же сильно напоминает фрагмент 5, но с одним отличием. Во фрагменте 5 несколько раз повторяется фрагмент 4, в рамках которого выполняется несколько итераций, и на каждой итерации внутри фрагмента 4 используются разные элементы (поскольку первый элемент сдвигается на 1). В случае данного фрагмента выполняются все те же итерации, но в перемешанном виде. Сначала выполняются все итерации, начинающиеся с одного и того же элемента; затем все итерации, который начинаются с элемента, чей индекс идет следующим; и т.д.&lt;br /&gt;
&lt;br /&gt;
Такой фрагмент обладает более высокой и пространственной, и временно́й локальностью по сравнению с фрагментом 5, поскольку обращения в одним и тем же элементам расположены ближе друг к другу в профиле.&lt;br /&gt;
&lt;br /&gt;
[[file:matrmult 11.PNG|thumb|center|700px|Рисунок 12. Начало фрагмента 6]]&lt;br /&gt;
[[file:matrmult 12.PNG|thumb|center|700px|Рисунок 13. Начало фрагмента 6, первые несколько итераций]]&lt;br /&gt;
&lt;br /&gt;
В итоге можно сказать, что наиболее низкой локальностью в целом обладают фрагменты 5 и 6. Фрагмент 4 также обладает низкой локальностью, однако содержит значительно меньшее число обращений, а значит, привносит меньший вклад в общий профиль обращений. Это позволяет определить, что наименее эффективными с точки зрения работы с памятью являются варианты kji и jki, поскольку каждый из них содержит фрагменты 5 и 6. Далее идут варианты ijk и jik – в них по одному такому фрагменту. Самые лучшие варианты – ikj и kij.&lt;br /&gt;
&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
&lt;br /&gt;
Основные фрагменты реализации, на основе которых были получены количественные оценки, приведены [http://git.algowiki-project.org/Voevodin/locality/blob/master/benchmarks/matrix_mult/matrix_mult.h здесь] (функция Kernel***, где *** - порядок циклов (напр., KernelIJK) ). Условия запуска описаны [http://git.algowiki-project.org/Voevodin/locality/blob/master/README.md здесь].&lt;br /&gt;
&lt;br /&gt;
Первая оценка выполняется на основе характеристики daps, которая оценивает число выполненных обращений (чтений и записей) в память в секунду. Данная характеристика является аналогом оценки flops применительно к работе с памятью и является в большей степени оценкой производительности взаимодействия с памятью, чем оценкой локальности. Однако она служит хорошим источником информации, в том числе для сравнения с результатами по следующей характеристике cvg.&lt;br /&gt;
&lt;br /&gt;
На рис.14 приведены значения daps для реализаций распространенных алгоритмов, отсортированные по возрастанию (чем больше daps, тем в общем случае выше производительность). Можно увидеть, что, как и предполагалось  наиболее эффективными являются варианты kij,ikj. Заметно хуже результат у вариантов jik,ijk, при этом эти варианты практически равны между собой. Самый плохой результат ожидаемо у вариантов jki,kji.&lt;br /&gt;
&lt;br /&gt;
[[file:matrmult daps ru.PNG|thumb|center|700px|Рисунок 14. Сравнение значений оценки daps]]&lt;br /&gt;
&lt;br /&gt;
Вторая характеристика – cvg – предназначена для получения более машинно-независимой оценки локальности. Она определяет, насколько часто в программе необходимо подтягивать данные в кэш-память. Соответственно, чем меньше значение cvg, тем реже это нужно делать, тем лучше локальность. &lt;br /&gt;
&lt;br /&gt;
На рис.15 приведены значения cvg для того же набора реализаций, отсортированные по убыванию (чем меньше cvg, тем в общем случае выше локальность). Относительное сравнение результатов по cvg в целом повторяет результаты daps.&lt;br /&gt;
&lt;br /&gt;
[[file:matrmult cvg.PNG|thumb|center|700px|Рисунок 15. Сравнение значений оценки cvg]]&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
&lt;br /&gt;
[[file:Масштабируемость перемножения матриц производительность.png|thumb|center|700px|Рисунок 16. Параллельная реализация произведения матриц Максимальная производительность. ]]&lt;br /&gt;
[[file:Масштабируемость параллельной реализации перемножения матриц Эффективность.png|thumb|center|700px|Рисунок 17. Параллельная реализация произведения матриц Максимальная эффективность. ]]&lt;br /&gt;
Набор изменяемых параметров запуска реализации алгоритма и границы значений параметров алгоритма: &lt;br /&gt;
*	число процессоров [4 : 1024]&lt;br /&gt;
*	размерность матрицы [1024 : 20480]&lt;br /&gt;
Эффективность выполнения реализации алгоритма&lt;br /&gt;
*	Минимальная эффективность 4,71%&lt;br /&gt;
*	Максимальная эффективность 31,72%&lt;br /&gt;
Оценка масштабируемости&lt;br /&gt;
*	По числу процессов: -0.0436 – при увеличении числа процессов эффективность убывает достаточно интенсивно на всей рассмотренной области изменений параметров запуска. Уменьшение эффективности на рассмотренной области работы параллельной программы звязано с увеличением числа пересылок с ростом числа процессов и как следствие ростом накладных расходов на организацию вычислений. Присутствует область, на которой при увеличении числа процессов эффективность возрастает, но при дальнейшем росте продолжает снижаться. Это объясняется декомпозицей данных, при которой наступает момент, когда размер матрицы позволяет блокам укладываться в КЭШ-память. Так же это подтверждает проявление этого явления, но со смещением по числу процессов, и при увеличении вычислительной сложности задачи.&lt;br /&gt;
*	По размеру задачи: -0.0255 – при увеличении размера задачи эффективность в целом уменьшается по рассматриваемой области, хотя и менее интенсивно, чем при увеличении числа процессов. Снижение эффективности объясняется тем, что при росте вычислительной сложности существенно возрастают объемы передаваемых данных. Присутствует область возрастания эффективности, на всех рассмотренных размерах матрицы. Это объясняется тем, что при малом размере задачи данные хорошо укладываются в КЭШ память, что приводит к высокой эффективности работы приложения при малом размере задачи. При дальнейшем увеличении размера эффективность уменьшается при выходе за границы КЭШ-памяти. &lt;br /&gt;
*	По двум направлениям: -0.000968 – при рассмотрении увеличения, как вычислительной сложности, так и числа процессов по всей рассмотренной области значений уменьшается, интенсивность уменьшения эффективности не очень высока. В совокупности с тем фактом, что разница между максимальной и минимальной эффективностью на рассмотренной области значений параметров составляет почти 25% говорит о том, что уменьшение эффективности по всей области довольно равномерное, но интенсивно лишь в не очень больших участках по площади. На остальной области значений параметров изменения эффективности не столь значительны и находятся на приблизительно одном и том же уровне.&lt;br /&gt;
&lt;br /&gt;
[http://git.algowiki-project.org/Teplov/Scalability/blob/master/matrixmult/matrixmult.c Реализация алгоритма на языке C].&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;br /&gt;
&lt;br /&gt;
[[Категория:Законченные статьи]]&lt;br /&gt;
[[Категория:Матричные операции]]&lt;br /&gt;
&lt;br /&gt;
[[En:Dense matrix multiplication]]&lt;/div&gt;</summary>
		<author><name>Algoman</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:Novikov_alexander&amp;diff=21471</id>
		<title>Обсуждение участника:Novikov alexander</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:Novikov_alexander&amp;diff=21471"/>
		<updated>2016-12-20T15:41:34Z</updated>

		<summary type="html">&lt;p&gt;Algoman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Замечания к [[Стабилизированный_метод_биспоряженных_градиентов_(BiCGSTAB)]] ==&lt;br /&gt;
&lt;br /&gt;
0) нужно указать конкретный вклад (пункты) каждого автора +&lt;br /&gt;
&lt;br /&gt;
1) пропущен пункт 1.5 &amp;quot;Схема реализации последовательного алгоритма&amp;quot; из-за чего сбита нумерация первой части, см [[Структура_описания_свойств_алгоритмов]] +&lt;br /&gt;
&lt;br /&gt;
2) большую подпись картинки из п 1.6 следует вынести в текст самого пункта +&lt;br /&gt;
&lt;br /&gt;
3) отсутствует оценка вычислительная мощности в п 1.10(1.9) +&lt;br /&gt;
&lt;br /&gt;
4) список литературы оформлен неправильно - см. как сделано в [[Разложение_Холецкого_(метод_квадратного_корня)]] +&lt;br /&gt;
&lt;br /&gt;
== Замечания ==&lt;br /&gt;
&lt;br /&gt;
* в названии: &amp;quot;биспоряженных&amp;quot; -&amp;gt; &amp;quot;бисопряженных&amp;quot; - как переименовать страницу? нигде найти не могу(&lt;br /&gt;
&lt;br /&gt;
[[Участник:Algoman|Algoman]] ([[Обсуждение участника:Algoman|обсуждение]]) 18:37, 20 декабря 2016 (MSK) : переименовал ([[Участник:EasyBreezy/Стабилизированный_метод_бисопряженных_градиентов_(BiCGSTAB)]])&lt;br /&gt;
&lt;br /&gt;
* во врезке и в остальных местах унифицировать использование n и N +&lt;br /&gt;
* во врезке: объем означает всего лишь количество - не понял, что имеется ввиду?&lt;br /&gt;
* во врезке: странно смотрятся вместе целая часть числа и О(..)&lt;br /&gt;
* убрать звездочку в виде символа умножения +&lt;br /&gt;
* слова span, dim лучше набирать  прямым шрифтом: {\rm ..} +&lt;br /&gt;
* описание итерационного процесса из 1.2 лучше разбросать по п.1.3-1.5 и дополнить их словесным описанием&lt;br /&gt;
* п.1.6: &amp;quot;нетрудоемкие&amp;quot; - лучше просто сказать что их мало +&lt;br /&gt;
* п.1.7 &amp;quot;числа на вектор&amp;quot; - лучше &amp;quot;вектора на число&amp;quot; +&lt;br /&gt;
* п.1.6 (и врезка): приведена сложность не всего алгоритма, а 1 итерации; лучше домножить на кол-во итераций +&lt;br /&gt;
* п.1.8: &amp;quot;высота/ширина матрицы&amp;quot; - вероятно ЯПФ матрицы&lt;br /&gt;
* п.1.8 (и др.): обозначения р в тексте заменять на математическое р, и т.д. +&lt;br /&gt;
* п.1.10: термин &amp;quot;вычислительная мощность&amp;quot; сделать отсылку в глоссарий&lt;br /&gt;
* п.2.4: почему же использовано такое небольшое количество процессоров? это же хорошо масштабируемый алгоритм&lt;br /&gt;
* п.2.4: размер матрицы [..] - с каким шагом?&lt;br /&gt;
* п.2.4: занумеровать рисунки&lt;br /&gt;
* п.2.4: добавить анализ результатов выших экспериментов&lt;br /&gt;
* п.2.7: существуют и другие реализации, постарайтесь добавить еще&lt;/div&gt;</summary>
		<author><name>Algoman</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:Novikov_alexander&amp;diff=21470</id>
		<title>Обсуждение участника:Novikov alexander</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:Novikov_alexander&amp;diff=21470"/>
		<updated>2016-12-20T15:37:44Z</updated>

		<summary type="html">&lt;p&gt;Algoman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Замечания к [[Стабилизированный_метод_биспоряженных_градиентов_(BiCGSTAB)]] ==&lt;br /&gt;
&lt;br /&gt;
0) нужно указать конкретный вклад (пункты) каждого автора +&lt;br /&gt;
&lt;br /&gt;
1) пропущен пункт 1.5 &amp;quot;Схема реализации последовательного алгоритма&amp;quot; из-за чего сбита нумерация первой части, см [[Структура_описания_свойств_алгоритмов]] +&lt;br /&gt;
&lt;br /&gt;
2) большую подпись картинки из п 1.6 следует вынести в текст самого пункта +&lt;br /&gt;
&lt;br /&gt;
3) отсутствует оценка вычислительная мощности в п 1.10(1.9) +&lt;br /&gt;
&lt;br /&gt;
4) список литературы оформлен неправильно - см. как сделано в [[Разложение_Холецкого_(метод_квадратного_корня)]] +&lt;br /&gt;
&lt;br /&gt;
== Замечания ==&lt;br /&gt;
&lt;br /&gt;
* в названии: &amp;quot;биспоряженных&amp;quot; -&amp;gt; &amp;quot;бисопряженных&amp;quot; - как переименовать страницу? нигде найти не могу(&lt;br /&gt;
&lt;br /&gt;
[[Участник:Algoman|Algoman]] ([[Обсуждение участника:Algoman|обсуждение]]) 18:37, 20 декабря 2016 (MSK) : переименовал&lt;br /&gt;
&lt;br /&gt;
* во врезке и в остальных местах унифицировать использование n и N +&lt;br /&gt;
* во врезке: объем означает всего лишь количество - не понял, что имеется ввиду?&lt;br /&gt;
* во врезке: странно смотрятся вместе целая часть числа и О(..)&lt;br /&gt;
* убрать звездочку в виде символа умножения +&lt;br /&gt;
* слова span, dim лучше набирать  прямым шрифтом: {\rm ..} +&lt;br /&gt;
* описание итерационного процесса из 1.2 лучше разбросать по п.1.3-1.5 и дополнить их словесным описанием&lt;br /&gt;
* п.1.6: &amp;quot;нетрудоемкие&amp;quot; - лучше просто сказать что их мало +&lt;br /&gt;
* п.1.7 &amp;quot;числа на вектор&amp;quot; - лучше &amp;quot;вектора на число&amp;quot; +&lt;br /&gt;
* п.1.6 (и врезка): приведена сложность не всего алгоритма, а 1 итерации; лучше домножить на кол-во итераций +&lt;br /&gt;
* п.1.8: &amp;quot;высота/ширина матрицы&amp;quot; - вероятно ЯПФ матрицы&lt;br /&gt;
* п.1.8 (и др.): обозначения р в тексте заменять на математическое р, и т.д. +&lt;br /&gt;
* п.1.10: термин &amp;quot;вычислительная мощность&amp;quot; сделать отсылку в глоссарий&lt;br /&gt;
* п.2.4: почему же использовано такое небольшое количество процессоров? это же хорошо масштабируемый алгоритм&lt;br /&gt;
* п.2.4: размер матрицы [..] - с каким шагом?&lt;br /&gt;
* п.2.4: занумеровать рисунки&lt;br /&gt;
* п.2.4: добавить анализ результатов выших экспериментов&lt;br /&gt;
* п.2.7: существуют и другие реализации, постарайтесь добавить еще&lt;/div&gt;</summary>
		<author><name>Algoman</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:EasyBreezy/%D0%A1%D1%82%D0%B0%D0%B1%D0%B8%D0%BB%D0%B8%D0%B7%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9_%D0%BC%D0%B5%D1%82%D0%BE%D0%B4_%D0%B1%D0%B8%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B3%D1%80%D0%B0%D0%B4%D0%B8%D0%B5%D0%BD%D1%82%D0%BE%D0%B2_(BiCGSTAB)&amp;diff=21469</id>
		<title>Участник:EasyBreezy/Стабилизированный метод бисопряженных градиентов (BiCGSTAB)</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:EasyBreezy/%D0%A1%D1%82%D0%B0%D0%B1%D0%B8%D0%BB%D0%B8%D0%B7%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9_%D0%BC%D0%B5%D1%82%D0%BE%D0%B4_%D0%B1%D0%B8%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B3%D1%80%D0%B0%D0%B4%D0%B8%D0%B5%D0%BD%D1%82%D0%BE%D0%B2_(BiCGSTAB)&amp;diff=21469"/>
		<updated>2016-12-20T15:36:54Z</updated>

		<summary type="html">&lt;p&gt;Algoman: Algoman переименовал страницу Участник:EasyBreezy/Стабилизированный метод биспоряженных градиентов (BiCGSTAB) в [[Участник:EasyBreezy/Стабилизированны…&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Основные авторы описания: [[Участник:Novikov alexander|Александр Новиков (1.4, 1.6, 1.7, 2.4, 2.7, 3)]], [[Участник:EasyBreezy|Гаврилов Алексей (1.1 - 1.3, 1.5, 1.8, 1.9, 2.7, 3)]]&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = BiCGSTAB&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt; O(I * N^2) &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; N &amp;lt;/math&amp;gt; - размерность СЛАУ, &amp;lt;math&amp;gt;I&amp;lt;/math&amp;gt; - количество итераций&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt; O(k*(6 \sqrt N + 4N + 5 \lceil \frac{N}{p} \rceil)) &amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt; 2 \sqrt N &amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = матрица &amp;lt;math&amp;gt;A \in R^{N \times N}&amp;lt;/math&amp;gt; ( &amp;lt;math&amp;gt;C^{N \times N}&amp;lt;/math&amp;gt; ) и вектор правой части &amp;lt;math&amp;gt;b \in R^N&amp;lt;/math&amp;gt; ( &amp;lt;math&amp;gt;C^N&amp;lt;/math&amp;gt; )&lt;br /&gt;
| output_data       = вектор решения системы &amp;lt;math&amp;gt;x \in R^N&amp;lt;/math&amp;gt; ( &amp;lt;math&amp;gt;C^N&amp;lt;/math&amp;gt; )&lt;br /&gt;
}}&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
:Стабилизированный метод бисопряженных градиентов, так же известный как BiCGSTAB (Biconjugate gradient stabilized method), был предложен голландским математиком Хенком ван дер Ворстом&amp;lt;ref&amp;gt;Henk A. vander Vorst, Iterative Krylov Methods for Large Linear Systems, Cambridge University Press 2003, 230p&amp;lt;/ref&amp;gt; в 1992 году. Статья, в которой описывался метод, стала самым цитируемым научным трудом в области математики в 1990х годах.&lt;br /&gt;
&lt;br /&gt;
:Метод появился, как ответ на задачу о построении способа решения систем линейных алгебраических уравнений произвольного вида. На момент появления BiCGSTAB уже существовали методы решения СЛАУ произвольного типа, в том числе и в комплексном пространстве, например метод бисопряженных градиентов. Однако существующие на тот момент методы либо обладали недостаточной скоростью сходимости, либо использовали в вычислениях тяжелые операции, такие как транспонирования матрицы, которые усложняли распараллеливание на многопроцессорных машинах.&lt;br /&gt;
:BiCGSTAB является итерационным методом решения систем линейных алгебраических уравнений. Мощь метода заключается в том, что его можно применять к матрицам общего вида, в том числе с комплексными коэффициентами. В процессе выполнения BiCGSTAB не использует для вычисления плохо распараллеливаемых операций, не допускает накопления погрешностей округления и нестабильного поведения невязки. Эти факторы выгодно отличают его от предшественников: метода бисопряженных градиентов и квадратичного метода сопряженных градиентов, из которого BiCGSTAB фактически и вытекает. К преимуществам так же можно добавить более высокую в общем случае скорость сходимости относительно ближайших конкурентов. Тем не менее, для некоторых видов СЛАУ BiCGSTAB может уступать более простым методам.&amp;lt;ref&amp;gt;Горбаченко В.И, Вычислительная линейная алгебра с примерами на MATLAB. — СПб.: БХВ-Петербург, 2011. — 320 с.: ил. — (Учебное пособие)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Благодаря свойствам алгоритма область применения метода весьма широка. Фактически, он используется во всех задачах, где требуется решать СЛАУ, в том числе СЛАУ большой размерности, к которым сводится большое количество численных методов, применяемых при решении задач математического моделирования. &lt;br /&gt;
&lt;br /&gt;
:BiCGSTAB относится к классу так называемых проекционных методов. Основная идея методов данного класса: искать итерационным способом наилучшее приближение решения в некотором подпространстве пространства &amp;lt;math&amp;gt;R^n&amp;lt;/math&amp;gt;, и чем шире подпространство, в котором ищется приближение решения, тем ближе будет приближенное решение к точному на каждой итерации. В качестве такого подпространства используются пространства Крылова, порожденные матрицей системы и невязкой первого приближения: &amp;lt;math&amp;gt;K^m (A, r^0) = \rm span(r^0, Ar^0, A^2r^0, ..., A^{m-1} r^0).&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;Горбаченко В.И, Вычислительная линейная алгебра с примерами на MATLAB. — СПб.: БХВ-Петербург, 2011. — 320 с.: ил. — (Учебное пособие)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:Изложим основную идею любого проекционного метода, заложенную в том числе и в BiCGSTAB. Для простоты выкладок и рассуждений здесь и далее будем считать, что матрица системы и ее правая часть вещественны. Без ограничения общности все дальнейшие рассуждения могут быть перенесены и на комплексный случай. Итак, пусть решается система &amp;lt;math&amp;gt;Ax=b&amp;lt;/math&amp;gt; с невырожденной матрицей  &amp;lt;math&amp;gt;A \in R^{n \times n}&amp;lt;/math&amp;gt; и ненулевым  вектором  &amp;lt;math&amp;gt;b \in R^n&amp;lt;/math&amp;gt;.  Имеются  два подпространства &amp;lt;math&amp;gt;K_n&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;L_n&amp;lt;/math&amp;gt;. Требуется найти вектор &amp;lt;math&amp;gt;x \in K_n&amp;lt;/math&amp;gt;, который обеспечивает решение  системы, оптимальное относительно подпространства  &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt;, то есть требуется выполнение условия Петрова-Галеркина: &amp;lt;math&amp;gt;(Ax,z)=(b,z), \forall z \in L_n&amp;lt;/math&amp;gt;. В данном случае вектор x называется обобщенным решением системы. &lt;br /&gt;
&lt;br /&gt;
:Условие Петрова-Галеркина можно записать и через определение невязки. Пусть &amp;lt;math&amp;gt;r = b - Ax&amp;lt;/math&amp;gt; - невязка, тогда условие Петрова-Галеркина перепишется в виде: &amp;lt;math&amp;gt;(b - Ax, z)=(r, z),\forall z \in L_n&amp;lt;/math&amp;gt;. Это равносильно тому, что вектор невязки ортогонален пространству &amp;lt;math&amp;gt;L_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
:Пусть для СЛАУ известно некоторое приближение &amp;lt;math&amp;gt;x^0&amp;lt;/math&amp;gt; точного решения &amp;lt;math&amp;gt;x^*&amp;lt;/math&amp;gt;. Данное приближение требуется уточнить поправкой &amp;lt;math&amp;gt; \delta: b - Ax^0 + \delta \perp L&amp;lt;/math&amp;gt;. Невязка уточненного решения имеет вид: &amp;lt;math&amp;gt;r_{new} = b - Ax^0 + \delta = r^0- A\delta&amp;lt;/math&amp;gt;. Условие Петрова-Галеркина тогда можно переписать так: &amp;lt;math&amp;gt;(r_{new}, z)= r^0 - (A\delta, z) = 0, \forall z \in L&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Пусть  &amp;lt;math&amp;gt;\rm dim K = dim L = m, V = (v_1, ..., v_n) \in R^{n \times m}, W = (w_1, ... w_n) \in R^{n \times m}&amp;lt;/math&amp;gt;, где &amp;lt;marh&amp;gt;V&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;W&amp;lt;/math&amp;gt; – матрицы, столбцы которых образуют базисы пространств &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt; соответственно. Пусть так же &amp;lt;math&amp;gt; \delta = Vy, z = Wq&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; – коэффициенты разложения вектора поправки по базису пространства &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; – коэффициенты разложения вектора &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt; в пространстве &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt;. Тогда новое приближение решения можно записать в виде: &amp;lt;math&amp;gt;x^1 = x^0 + \delta= x^0 + Vy&amp;lt;/math&amp;gt;. Из условия ортогональности Петрова-Галеркина получаем, что: &amp;lt;math&amp;gt;(r - AVy, Wq) = (W^Tr^0 - AVy, q) = 0&amp;lt;/math&amp;gt;. Поскольку &amp;lt;math&amp;gt;q \neq 0&amp;lt;/math&amp;gt;, то получаем СЛАУ для вектора &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;W^TAVy = W^Tr^0&amp;lt;/math&amp;gt;. Если предположить, что матрица &amp;lt;math&amp;gt;W^TAVy&amp;lt;/math&amp;gt; невырождена, то вектор y однозначно определяется и равен: &amp;lt;math&amp;gt;y = W^TAV^{-1}W^Tr^0&amp;lt;/math&amp;gt;. Подставляя найденные коэффициенты разложения в выражение для первого приближения получаем: &amp;lt;math&amp;gt;x^1 = x^0 + \delta = x^0 + W^TAV^{-1}W^Tr^0y&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Подведем итог. Общий порядок шагов любого проекционного метода следующий:&lt;br /&gt;
#Выбрать пару подпространств &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt;&lt;br /&gt;
#Найти базис V пространства K и базис W пространства &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt;;&lt;br /&gt;
#Вычислить невязку&lt;br /&gt;
#Найти &amp;lt;math&amp;gt;y = W^T AV^{-1} W^T r^0&amp;lt;/math&amp;gt;&lt;br /&gt;
#Положить &amp;lt;math&amp;gt;x = x + Vy&amp;lt;/math&amp;gt;&lt;br /&gt;
#Если не достигнут критерий остановки итерационного процесса, то повторить алгоритм, начиная с первого шага.&lt;br /&gt;
&lt;br /&gt;
:Как будет показано далее, в BiCGSTAB не требуется вычислять матрицу  &amp;lt;math&amp;gt;W^T AV^{-1}&amp;lt;/math&amp;gt; в явном виде.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
:Рассмотрим СЛАУ с вещественными коэффициентами:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;Ax = b, A \in R^{N \times N}, b \in R^N&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
:В основу алгоритма ложиться идея проекционного метода и использование свойства A-бисопряженности системы векторов, а именно: векторы &amp;lt;math&amp;gt;p^1, p^2, ...&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\overline p^1, \overline p^2, ...&amp;lt;/math&amp;gt; бисопряжены, если &amp;lt;math&amp;gt;(Ap^i,p^j ) = 0,&amp;lt;/math&amp;gt; при &amp;lt;math&amp;gt;i \neq j&amp;lt;/math&amp;gt;. Фактически, данное условие эквивалентно биортогональности относительно энергетического скалярного произведения. &lt;br /&gt;
 &lt;br /&gt;
:Общая концепция проекционных методов предписывает нам выбрать два подпространства. В нашем случае подпространства мы выберем два подпространства, задаваемые матрицей системы А, вектором невязки на нулевой итерации &amp;lt;math&amp;gt;r^0&amp;lt;/math&amp;gt; и вектором &amp;lt;math&amp;gt;\overline r^0&amp;lt;/math&amp;gt;. который выбирается из условия &amp;lt;math&amp;gt;(r^0, \overline r^0) \neq 0&amp;lt;/math&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;K = K^k(A, r^0), L = K^k(A, \overline r^0)&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Метод основан на построении биортогонального базиса &amp;lt;math&amp;gt;p^0, p^1, ... p^k .. &amp;lt;/math&amp;gt; пространства &amp;lt;math&amp;gt;K^k (A, r^0) &amp;lt;/math&amp;gt; и вычислении поправки такой, что новое приближение на очередной итерации было бы ортогонально второму подпространству Крылова. Базисные вектора строятся до тех пор, пока не будет достигнут критерий остановки итерационного процесса, а каждое последующее приближение формируется, как сумма приближения на предыдущей итерации и найденной поправки. Критерием останова итерационного процесса является достижения невязкой значения, которое меньше некоторого наперед заданного числа &amp;lt;math&amp;gt;\epsilon&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
:Основной итерационный процесс задается формулами:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;x^{k + 1} = x^k + \alpha_k p_k + \omega_k s_k&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;p^{k + 1} = r^{k + 1} + \beta_k p_k - \omega_k Ap_k&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
:где:&lt;br /&gt;
#&amp;lt;math&amp;gt;x^{k + 1}&amp;lt;/math&amp;gt; - приближение на следующей итерации&lt;br /&gt;
#&amp;lt;math&amp;gt;x^k&amp;lt;/math&amp;gt; - приближение на предыдущей итерации&lt;br /&gt;
#&amp;lt;math&amp;gt;p_k&amp;lt;/math&amp;gt; - базисный вектор подпространства Крылова, порожденного матрице СЛАУ и невязкой&lt;br /&gt;
#&amp;lt;math&amp;gt;\alpha_k, \omega_k&amp;lt;/math&amp;gt; - вспомогательные скаляры, определяемые для каждого шага итерации&lt;br /&gt;
#&amp;lt;math&amp;gt;s_k&amp;lt;/math&amp;gt; - вспомогательный вектор&lt;br /&gt;
#&amp;lt;math&amp;gt;p^{k + 1}&amp;lt;/math&amp;gt; - &amp;lt;math&amp;gt;k + 1&amp;lt;/math&amp;gt;-ый базисный вектор&lt;br /&gt;
#&amp;lt;math&amp;gt;r^{k + 1}&amp;lt;/math&amp;gt; - невязка &amp;lt;math&amp;gt;k + 1&amp;lt;/math&amp;gt;-ой итерации&lt;br /&gt;
#&amp;lt;math&amp;gt;\beta_k&amp;lt;/math&amp;gt; - вспомогательный коэффициент&lt;br /&gt;
&lt;br /&gt;
:Вспомогательный вектор выражается следующим образом:&lt;br /&gt;
*&amp;lt;math&amp;gt;s_k = r^k - \alpha_k Ap_k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Вспомогательные коэффициенты вычисляются по формулам:&lt;br /&gt;
*&amp;lt;math&amp;gt;\alpha_k = \frac{(r^k, \overline r^0)}{(Ap_k, \overline r^0)}&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;\omega_k = \frac{(As_k, s_k)}{(As_k, As_k)}&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;\beta_k = \frac{(r^{k + 1}, \overline r^0)}{(r^k, \overline r^0)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Подведем итог и запишем итерационный процесс&lt;br /&gt;
:Подготовительный этап:&lt;br /&gt;
#Выбирается некоторое начальное приближение &amp;lt;math&amp;gt;x^0&amp;lt;/math&amp;gt;&lt;br /&gt;
#По выбранному приближению находится невязка &amp;lt;math&amp;gt;r^0 = b - Ax^0&amp;lt;/math&amp;gt;&lt;br /&gt;
#Из условия &amp;lt;math&amp;gt;(r^0, \overline r^0) \neq 0&amp;lt;/math&amp;gt; выбирается вектор &amp;lt;math&amp;gt;\overline r^0&amp;lt;/math&amp;gt;&lt;br /&gt;
#Положим &amp;lt;math&amp;gt;p^0 = r^0&amp;lt;/math&amp;gt;&lt;br /&gt;
#Устанавливаем счетчик итераций: &amp;lt;math&amp;gt;n = 0&amp;lt;/math&amp;gt;&lt;br /&gt;
:Итерационный процесс:&lt;br /&gt;
#Находим &amp;lt;math&amp;gt;\alpha_k&amp;lt;/math&amp;gt;&lt;br /&gt;
#По найденному &amp;lt;math&amp;gt;\alpha_k&amp;lt;/math&amp;gt; вычисляем &amp;lt;math&amp;gt;s_k&amp;lt;/math&amp;gt;&lt;br /&gt;
#По найденному &amp;lt;math&amp;gt;s_k&amp;lt;/math&amp;gt; вычисляется вспомогательный коэффициент &amp;lt;math&amp;gt;\omega_k&amp;lt;/math&amp;gt;&lt;br /&gt;
#Находится новое приближение &amp;lt;math&amp;gt;x^{k + 1}&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вычисляется невязка &amp;lt;math&amp;gt;r^{k + 1}&amp;lt;/math&amp;gt;. Если выполнено условие &amp;lt;math&amp;gt;\parallel r^{k + 1} \parallel &amp;lt; \epsilon&amp;lt;/math&amp;gt;, то алгоритм завершается.&lt;br /&gt;
#Вычисляется вспомогательный коэффициент &amp;lt;math&amp;gt;\beta_k&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вычисляется новый базисный вектор: &amp;lt;math&amp;gt;p^{k + 1}&amp;lt;/math&amp;gt;&lt;br /&gt;
#Увеличивается номер итерации: &amp;lt;math&amp;gt;n = n + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
#Переход к первому шагу итерационного процесса.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
:Вычислительное ядро полностью совпадает с итерационным процессом. Подготовка к итерационному процессу в ядро не включается.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
На каждой итерации алгоритма используются:&lt;br /&gt;
# [[Скалярное произведение векторов, вещественная версия, последовательно-параллельный вариант]] x 4 раза&lt;br /&gt;
# [[Умножение плотной матрицы на вектор ]] х 2 раза&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
:Всего в вычислительном блоке алгоритма присутствует 20 трудоемких операций: 2 операции умножения матрицы на вектор, 6 скалярных произведений и 6 сложений/вычитаний векторов и 6 умножений вектора на число.&lt;br /&gt;
&lt;br /&gt;
:Каждое скалярное произведение требует &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; произведений и &amp;lt;math&amp;gt;N - 1&amp;lt;/math&amp;gt; сложение, то есть &amp;lt;math&amp;gt;2N - 1&amp;lt;/math&amp;gt; операции. Скалярных произведений всего 6 штук (включая поиск нормы), что дает нам &amp;lt;math&amp;gt;12N - 6&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
:Умножение матрицы размерности &amp;lt;math&amp;gt;N \times N&amp;lt;/math&amp;gt; на вектор эквивалентно взятию еще &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; скаляров, и так как таких операций в вычислительном ядре 2, то дополнительно имеется еще &amp;lt;math&amp;gt;2N(2N - 1)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
:Наконец, сложение или вычитание векторов требует &amp;lt;math&amp;gt;6N&amp;lt;/math&amp;gt; соотвествующих операций. Столько же требует 6 произведений вектора на число.&lt;br /&gt;
&lt;br /&gt;
:Итого: &amp;lt;math&amp;gt;2N(2N - 1) + 12N - 6 + 6N + 6N = 4N^2 + 22N - 6&amp;lt;/math&amp;gt; операций за одну итерацию. Домножая это на количество итераций &amp;lt;math&amp;gt;I&amp;lt;/math&amp;gt;, получаем итоговую сложность алгоритма: &amp;lt;math&amp;gt;I * (4N^2 + 22N - 6)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Имеются так же операции как, извлечение квадратного корня и деление вещественных чисел друг на друга, но они не принимаются в расчет, так как они не влияют на итоговый результат. Окончательно можно заключить, что последовательная сложность алгоритма эквивалента &amp;lt;math&amp;gt;O(I * N^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
[[file:BiCGStabIterations.jpg|thumb|center|800px|&amp;lt;center&amp;gt;Информационный граф.&amp;lt;/center&amp;gt;]]&lt;br /&gt;
На графе представлены связи между операциями, выполняющимися в первых трех итерациях метода. При выполнении большего, чем 3, количества итераций, структура каждой новой будет повторять структуру третьей. Связи между итерациями не представлены, т.к. они не важны для понимания параллельной структуры алгоритма. Серым обозначено перемножение чисел, красным - умножение числа на вектор&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
Основной прирост производительности параллельной версии алгоритма дает использование параллельных операций вычисления скалярного произведения, суммы векторов, а так же произведения матрицы на вектор. Каждая из операций вычисления скалярного произведения и суммы векторов, выполняемая на &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; процессорах, за счет метода сдваивания может ускориться до &amp;lt;math&amp;gt; \frac{p}{\log_2 p} &amp;lt;/math&amp;gt; раз. Ускорение же умножения матрицы на вектор может достигать &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; раз.&lt;br /&gt;
&lt;br /&gt;
Ширина и высота ЯПФ графа данного алгоритма напрямую зависит от конкретных реализаций макроопераций и входных данных.&lt;br /&gt;
&lt;br /&gt;
Для последовательно-параллельной реализации операции взятия скалярного произведения в наиболее оптимальном случае (&amp;lt;math&amp;gt;p= \sqrt N&amp;lt;/math&amp;gt;) высота будет равна &amp;lt;math&amp;gt;2 \sqrt N - 1&amp;lt;/math&amp;gt;, а ширина &amp;lt;math&amp;gt;\sqrt 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;2N&amp;lt;/math&amp;gt;, а ширина &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - это уже упомянутая длина вектора(она же ширина матрицы), а m - высота матрицы.&lt;br /&gt;
&lt;br /&gt;
Высота ЯПФ операции умножения вектора на число равна &amp;lt;math&amp;gt;\frac{N}{p}&amp;lt;/math&amp;gt;, а ширина &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Высота ЯПФ операции вычисления разности векторов = &amp;lt;math&amp;gt; \log_2 p &amp;lt;/math&amp;gt;, а ширина &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В конечном счете общую высоту ЯПФ одной итерации алгоритма можно оценить, как &amp;lt;math&amp;gt;6 \sqrt N-3 + 4N + 3 + 1 + 3\lceil \frac{N}{p} \rceil + 2 \lceil \frac{N}{p} \rceil = 6 \sqrt N + 4N + 5 \lceil \frac{N}{p} \rceil + 1&amp;lt;/math&amp;gt;, а ширину, как &amp;lt;math&amp;gt;2 \sqrt N&amp;lt;/math&amp;gt;, если не брать в рассчет проверку критерия сходимости и упрощенности первой итерации по сравнению с остальными.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
:Входные данные&lt;br /&gt;
#Матрица &amp;lt;math&amp;gt;A \in R^{N \times N}&amp;lt;/math&amp;gt; ( &amp;lt;math&amp;gt;C^{N \times N}&amp;lt;/math&amp;gt; )&lt;br /&gt;
#Вектор правой части &amp;lt;math&amp;gt;b \in R^N&amp;lt;/math&amp;gt; ( &amp;lt;math&amp;gt;C^N&amp;lt;/math&amp;gt; )&lt;br /&gt;
&lt;br /&gt;
:Выходные данные:&lt;br /&gt;
#Вектор решения СЛАУ &amp;lt;math&amp;gt;x \in R^N&amp;lt;/math&amp;gt; ( &amp;lt;math&amp;gt;C^N&amp;lt;/math&amp;gt; )&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
:BiCGSTAB хорошо зарекомендовал себя для решения систем линейных алгебраический уравнений, поскольку обладает некоторыми важными свойствами:&lt;br /&gt;
#Благодаря применению подхода Петрова-Галеркина и техники ортогонализации, он численно устойчив&lt;br /&gt;
#Не меняется вид матрицы в процессе решения&lt;br /&gt;
#Эффективен для решения систем большой размерности с разреженной матрицей, поскольку в методе самая трудоемкая операция - умножение матрицы на вектор&lt;br /&gt;
#Лучше подходит под распределенные системы, поскольку не содержит операции транспонирования матрицы&lt;br /&gt;
#Применим для решения систем с несимметричными матрицами.&lt;br /&gt;
#Вычислительная мощность: &amp;lt;math&amp;gt;N/4&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
===== Анализ на основе теста Apex-Map =====&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
Исследование масштабируемости реализации стабилизированного метода бисопряженных градиентов проводилось согласно [[Scalability methodology|методике]]  на суперкомпьютере &amp;quot;Ломоносов&amp;quot;&amp;lt;ref name=&amp;quot;Lom&amp;quot;&amp;gt;Воеводин Вл., Жуматий С., Соболев С., Антонов А., Брызгалов П., Никитенко Д., Стефанов К., Воеводин Вад. Практика суперкомпьютера «Ломоносов» // Открытые системы, 2012, N 7, С. 36-39.&amp;lt;/ref&amp;gt; [http://parallel.ru/cluster Суперкомпьютерного комплекса Московского университета].&lt;br /&gt;
&lt;br /&gt;
Набор и границы значений изменяемых [[Глоссарий#Параметры запуска|параметров запуска]] реализации алгоритма: &lt;br /&gt;
&lt;br /&gt;
*	число процессоров [2 : 16] с шагом 1;&lt;br /&gt;
*	размер матрицы [262144 : 11239424].&lt;br /&gt;
&lt;br /&gt;
В результате проведённых экспериментов был получен следующий диапазон [[Глоссарий#Эффективность реализации|эффективности реализации]] алгоритма:&lt;br /&gt;
&lt;br /&gt;
*	минимальная эффективность реализации 60,00%;&lt;br /&gt;
*	максимальная эффективность реализации 98,33%.&lt;br /&gt;
&lt;br /&gt;
На следующих рисунках приведены графики [[Глоссарий#Производительность|производительности]] и эффективности выбранной реализации стабилизированного метода бисопряженных градиентов в зависимости от изменяемых параметров запуска.&lt;br /&gt;
&lt;br /&gt;
[[file:Масштабируемость параллельной реализации BiCGSTAB Производительность.png|thumb|center|700px|Параллельная реализация стабилизированного метода бисопряженных градиентов. Изменение производительности в зависимости от числа процессоров и размера матрицы.]]&lt;br /&gt;
[[file:Масштабируемость параллельной реализации BiCGSTAB эффективность.png|thumb|center|700px|Параллельная реализация стабилизированного метода бисопряженных градиентов. Изменение эффективности в зависимости от числа процессоров и размера матрицы.]]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/LLNL/hypre/blob/master/src/krylov/HYPRE_bicgstab.c Исследованная параллельная реализация на языке C]&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
* Параллельная реализация алгоритма, предложенная MIT: [http://ab-initio.mit.edu/~meep/meep/src/bicgstab.cpp MIT BiCGSTAB]&lt;br /&gt;
* Параллельная реализация алгоритма в бесплатной библиотеке, поддерживающей MPI и OpenMP, HYPRE: [http://acts.nersc.gov/hypre/ Официальная страница] [https://github.com/LLNL/hypre/blob/master/src/krylov/bicgstab.c Исходный код]&lt;br /&gt;
* Параллельная реализация алгоритма на CUDA в условно бесплатной библиотеке [https://developer.nvidia.com/amgx/ NVIDIA AmgX]&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;/div&gt;</summary>
		<author><name>Algoman</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:EasyBreezy/%D0%A1%D1%82%D0%B0%D0%B1%D0%B8%D0%BB%D0%B8%D0%B7%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9_%D0%BC%D0%B5%D1%82%D0%BE%D0%B4_%D0%B1%D0%B8%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B3%D1%80%D0%B0%D0%B4%D0%B8%D0%B5%D0%BD%D1%82%D0%BE%D0%B2_(BiCGSTAB)&amp;diff=21468</id>
		<title>Участник:EasyBreezy/Стабилизированный метод бисопряженных градиентов (BiCGSTAB)</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:EasyBreezy/%D0%A1%D1%82%D0%B0%D0%B1%D0%B8%D0%BB%D0%B8%D0%B7%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9_%D0%BC%D0%B5%D1%82%D0%BE%D0%B4_%D0%B1%D0%B8%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B3%D1%80%D0%B0%D0%B4%D0%B8%D0%B5%D0%BD%D1%82%D0%BE%D0%B2_(BiCGSTAB)&amp;diff=21468"/>
		<updated>2016-12-20T15:35:10Z</updated>

		<summary type="html">&lt;p&gt;Algoman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Основные авторы описания: [[Участник:Novikov alexander|Александр Новиков (1.4, 1.6, 1.7, 2.4, 2.7, 3)]], [[Участник:EasyBreezy|Гаврилов Алексей (1.1 - 1.3, 1.5, 1.8, 1.9, 2.7, 3)]]&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = BiCGSTAB&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt; O(I * N^2) &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; N &amp;lt;/math&amp;gt; - размерность СЛАУ, &amp;lt;math&amp;gt;I&amp;lt;/math&amp;gt; - количество итераций&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt; O(k*(6 \sqrt N + 4N + 5 \lceil \frac{N}{p} \rceil)) &amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt; 2 \sqrt N &amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = матрица &amp;lt;math&amp;gt;A \in R^{N \times N}&amp;lt;/math&amp;gt; ( &amp;lt;math&amp;gt;C^{N \times N}&amp;lt;/math&amp;gt; ) и вектор правой части &amp;lt;math&amp;gt;b \in R^N&amp;lt;/math&amp;gt; ( &amp;lt;math&amp;gt;C^N&amp;lt;/math&amp;gt; )&lt;br /&gt;
| output_data       = вектор решения системы &amp;lt;math&amp;gt;x \in R^N&amp;lt;/math&amp;gt; ( &amp;lt;math&amp;gt;C^N&amp;lt;/math&amp;gt; )&lt;br /&gt;
}}&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
:Стабилизированный метод бисопряженных градиентов, так же известный как BiCGSTAB (Biconjugate gradient stabilized method), был предложен голландским математиком Хенком ван дер Ворстом&amp;lt;ref&amp;gt;Henk A. vander Vorst, Iterative Krylov Methods for Large Linear Systems, Cambridge University Press 2003, 230p&amp;lt;/ref&amp;gt; в 1992 году. Статья, в которой описывался метод, стала самым цитируемым научным трудом в области математики в 1990х годах.&lt;br /&gt;
&lt;br /&gt;
:Метод появился, как ответ на задачу о построении способа решения систем линейных алгебраических уравнений произвольного вида. На момент появления BiCGSTAB уже существовали методы решения СЛАУ произвольного типа, в том числе и в комплексном пространстве, например метод бисопряженных градиентов. Однако существующие на тот момент методы либо обладали недостаточной скоростью сходимости, либо использовали в вычислениях тяжелые операции, такие как транспонирования матрицы, которые усложняли распараллеливание на многопроцессорных машинах.&lt;br /&gt;
:BiCGSTAB является итерационным методом решения систем линейных алгебраических уравнений. Мощь метода заключается в том, что его можно применять к матрицам общего вида, в том числе с комплексными коэффициентами. В процессе выполнения BiCGSTAB не использует для вычисления плохо распараллеливаемых операций, не допускает накопления погрешностей округления и нестабильного поведения невязки. Эти факторы выгодно отличают его от предшественников: метода бисопряженных градиентов и квадратичного метода сопряженных градиентов, из которого BiCGSTAB фактически и вытекает. К преимуществам так же можно добавить более высокую в общем случае скорость сходимости относительно ближайших конкурентов. Тем не менее, для некоторых видов СЛАУ BiCGSTAB может уступать более простым методам.&amp;lt;ref&amp;gt;Горбаченко В.И, Вычислительная линейная алгебра с примерами на MATLAB. — СПб.: БХВ-Петербург, 2011. — 320 с.: ил. — (Учебное пособие)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Благодаря свойствам алгоритма область применения метода весьма широка. Фактически, он используется во всех задачах, где требуется решать СЛАУ, в том числе СЛАУ большой размерности, к которым сводится большое количество численных методов, применяемых при решении задач математического моделирования. &lt;br /&gt;
&lt;br /&gt;
:BiCGSTAB относится к классу так называемых проекционных методов. Основная идея методов данного класса: искать итерационным способом наилучшее приближение решения в некотором подпространстве пространства &amp;lt;math&amp;gt;R^n&amp;lt;/math&amp;gt;, и чем шире подпространство, в котором ищется приближение решения, тем ближе будет приближенное решение к точному на каждой итерации. В качестве такого подпространства используются пространства Крылова, порожденные матрицей системы и невязкой первого приближения: &amp;lt;math&amp;gt;K^m (A, r^0) = \rm span(r^0, Ar^0, A^2r^0, ..., A^{m-1} r^0).&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;Горбаченко В.И, Вычислительная линейная алгебра с примерами на MATLAB. — СПб.: БХВ-Петербург, 2011. — 320 с.: ил. — (Учебное пособие)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:Изложим основную идею любого проекционного метода, заложенную в том числе и в BiCGSTAB. Для простоты выкладок и рассуждений здесь и далее будем считать, что матрица системы и ее правая часть вещественны. Без ограничения общности все дальнейшие рассуждения могут быть перенесены и на комплексный случай. Итак, пусть решается система &amp;lt;math&amp;gt;Ax=b&amp;lt;/math&amp;gt; с невырожденной матрицей  &amp;lt;math&amp;gt;A \in R^{n \times n}&amp;lt;/math&amp;gt; и ненулевым  вектором  &amp;lt;math&amp;gt;b \in R^n&amp;lt;/math&amp;gt;.  Имеются  два подпространства &amp;lt;math&amp;gt;K_n&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;L_n&amp;lt;/math&amp;gt;. Требуется найти вектор &amp;lt;math&amp;gt;x \in K_n&amp;lt;/math&amp;gt;, который обеспечивает решение  системы, оптимальное относительно подпространства  &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt;, то есть требуется выполнение условия Петрова-Галеркина: &amp;lt;math&amp;gt;(Ax,z)=(b,z), \forall z \in L_n&amp;lt;/math&amp;gt;. В данном случае вектор x называется обобщенным решением системы. &lt;br /&gt;
&lt;br /&gt;
:Условие Петрова-Галеркина можно записать и через определение невязки. Пусть &amp;lt;math&amp;gt;r = b - Ax&amp;lt;/math&amp;gt; - невязка, тогда условие Петрова-Галеркина перепишется в виде: &amp;lt;math&amp;gt;(b - Ax, z)=(r, z),\forall z \in L_n&amp;lt;/math&amp;gt;. Это равносильно тому, что вектор невязки ортогонален пространству &amp;lt;math&amp;gt;L_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
:Пусть для СЛАУ известно некоторое приближение &amp;lt;math&amp;gt;x^0&amp;lt;/math&amp;gt; точного решения &amp;lt;math&amp;gt;x^*&amp;lt;/math&amp;gt;. Данное приближение требуется уточнить поправкой &amp;lt;math&amp;gt; \delta: b - Ax^0 + \delta \perp L&amp;lt;/math&amp;gt;. Невязка уточненного решения имеет вид: &amp;lt;math&amp;gt;r_{new} = b - Ax^0 + \delta = r^0- A\delta&amp;lt;/math&amp;gt;. Условие Петрова-Галеркина тогда можно переписать так: &amp;lt;math&amp;gt;(r_{new}, z)= r^0 - (A\delta, z) = 0, \forall z \in L&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Пусть  &amp;lt;math&amp;gt;\rm dim K = dim L = m, V = (v_1, ..., v_n) \in R^{n \times m}, W = (w_1, ... w_n) \in R^{n \times m}&amp;lt;/math&amp;gt;, где &amp;lt;marh&amp;gt;V&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;W&amp;lt;/math&amp;gt; – матрицы, столбцы которых образуют базисы пространств &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt; соответственно. Пусть так же &amp;lt;math&amp;gt; \delta = Vy, z = Wq&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; – коэффициенты разложения вектора поправки по базису пространства &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt;, а &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; – коэффициенты разложения вектора &amp;lt;math&amp;gt;z&amp;lt;/math&amp;gt; в пространстве &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt;. Тогда новое приближение решения можно записать в виде: &amp;lt;math&amp;gt;x^1 = x^0 + \delta= x^0 + Vy&amp;lt;/math&amp;gt;. Из условия ортогональности Петрова-Галеркина получаем, что: &amp;lt;math&amp;gt;(r - AVy, Wq) = (W^Tr^0 - AVy, q) = 0&amp;lt;/math&amp;gt;. Поскольку &amp;lt;math&amp;gt;q \neq 0&amp;lt;/math&amp;gt;, то получаем СЛАУ для вектора &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;W^TAVy = W^Tr^0&amp;lt;/math&amp;gt;. Если предположить, что матрица &amp;lt;math&amp;gt;W^TAVy&amp;lt;/math&amp;gt; невырождена, то вектор y однозначно определяется и равен: &amp;lt;math&amp;gt;y = W^TAV^{-1}W^Tr^0&amp;lt;/math&amp;gt;. Подставляя найденные коэффициенты разложения в выражение для первого приближения получаем: &amp;lt;math&amp;gt;x^1 = x^0 + \delta = x^0 + W^TAV^{-1}W^Tr^0y&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Подведем итог. Общий порядок шагов любого проекционного метода следующий:&lt;br /&gt;
#Выбрать пару подпространств &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt;&lt;br /&gt;
#Найти базис V пространства K и базис W пространства &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt;;&lt;br /&gt;
#Вычислить невязку&lt;br /&gt;
#Найти &amp;lt;math&amp;gt;y = W^T AV^{-1} W^T r^0&amp;lt;/math&amp;gt;&lt;br /&gt;
#Положить &amp;lt;math&amp;gt;x = x + Vy&amp;lt;/math&amp;gt;&lt;br /&gt;
#Если не достигнут критерий остановки итерационного процесса, то повторить алгоритм, начиная с первого шага.&lt;br /&gt;
&lt;br /&gt;
:Как будет показано далее, в BiCGSTAB не требуется вычислять матрицу  &amp;lt;math&amp;gt;W^T AV^{-1}&amp;lt;/math&amp;gt; в явном виде.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
:Рассмотрим СЛАУ с вещественными коэффициентами:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;Ax = b, A \in R^{N \times N}, b \in R^N&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
:В основу алгоритма ложиться идея проекционного метода и использование свойства A-бисопряженности системы векторов, а именно: векторы &amp;lt;math&amp;gt;p^1, p^2, ...&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\overline p^1, \overline p^2, ...&amp;lt;/math&amp;gt; бисопряжены, если &amp;lt;math&amp;gt;(Ap^i,p^j ) = 0,&amp;lt;/math&amp;gt; при &amp;lt;math&amp;gt;i \neq j&amp;lt;/math&amp;gt;. Фактически, данное условие эквивалентно биортогональности относительно энергетического скалярного произведения. &lt;br /&gt;
 &lt;br /&gt;
:Общая концепция проекционных методов предписывает нам выбрать два подпространства. В нашем случае подпространства мы выберем два подпространства, задаваемые матрицей системы А, вектором невязки на нулевой итерации &amp;lt;math&amp;gt;r^0&amp;lt;/math&amp;gt; и вектором &amp;lt;math&amp;gt;\overline r^0&amp;lt;/math&amp;gt;. который выбирается из условия &amp;lt;math&amp;gt;(r^0, \overline r^0) \neq 0&amp;lt;/math&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;K = K^k(A, r^0), L = K^k(A, \overline r^0)&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Метод основан на построении биортогонального базиса &amp;lt;math&amp;gt;p^0, p^1, ... p^k .. &amp;lt;/math&amp;gt; пространства &amp;lt;math&amp;gt;K^k (A, r^0) &amp;lt;/math&amp;gt; и вычислении поправки такой, что новое приближение на очередной итерации было бы ортогонально второму подпространству Крылова. Базисные вектора строятся до тех пор, пока не будет достигнут критерий остановки итерационного процесса, а каждое последующее приближение формируется, как сумма приближения на предыдущей итерации и найденной поправки. Критерием останова итерационного процесса является достижения невязкой значения, которое меньше некоторого наперед заданного числа &amp;lt;math&amp;gt;\epsilon&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
:Основной итерационный процесс задается формулами:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;x^{k + 1} = x^k + \alpha_k p_k + \omega_k s_k&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;p^{k + 1} = r^{k + 1} + \beta_k p_k - \omega_k Ap_k&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
:где:&lt;br /&gt;
#&amp;lt;math&amp;gt;x^{k + 1}&amp;lt;/math&amp;gt; - приближение на следующей итерации&lt;br /&gt;
#&amp;lt;math&amp;gt;x^k&amp;lt;/math&amp;gt; - приближение на предыдущей итерации&lt;br /&gt;
#&amp;lt;math&amp;gt;p_k&amp;lt;/math&amp;gt; - базисный вектор подпространства Крылова, порожденного матрице СЛАУ и невязкой&lt;br /&gt;
#&amp;lt;math&amp;gt;\alpha_k, \omega_k&amp;lt;/math&amp;gt; - вспомогательные скаляры, определяемые для каждого шага итерации&lt;br /&gt;
#&amp;lt;math&amp;gt;s_k&amp;lt;/math&amp;gt; - вспомогательный вектор&lt;br /&gt;
#&amp;lt;math&amp;gt;p^{k + 1}&amp;lt;/math&amp;gt; - &amp;lt;math&amp;gt;k + 1&amp;lt;/math&amp;gt;-ый базисный вектор&lt;br /&gt;
#&amp;lt;math&amp;gt;r^{k + 1}&amp;lt;/math&amp;gt; - невязка &amp;lt;math&amp;gt;k + 1&amp;lt;/math&amp;gt;-ой итерации&lt;br /&gt;
#&amp;lt;math&amp;gt;\beta_k&amp;lt;/math&amp;gt; - вспомогательный коэффициент&lt;br /&gt;
&lt;br /&gt;
:Вспомогательный вектор выражается следующим образом:&lt;br /&gt;
*&amp;lt;math&amp;gt;s_k = r^k - \alpha_k Ap_k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Вспомогательные коэффициенты вычисляются по формулам:&lt;br /&gt;
*&amp;lt;math&amp;gt;\alpha_k = \frac{(r^k, \overline r^0)}{(Ap_k, \overline r^0)}&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;\omega_k = \frac{(As_k, s_k)}{(As_k, As_k)}&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;\beta_k = \frac{(r^{k + 1}, \overline r^0)}{(r^k, \overline r^0)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Подведем итог и запишем итерационный процесс&lt;br /&gt;
:Подготовительный этап:&lt;br /&gt;
#Выбирается некоторое начальное приближение &amp;lt;math&amp;gt;x^0&amp;lt;/math&amp;gt;&lt;br /&gt;
#По выбранному приближению находится невязка &amp;lt;math&amp;gt;r^0 = b - Ax^0&amp;lt;/math&amp;gt;&lt;br /&gt;
#Из условия &amp;lt;math&amp;gt;(r^0, \overline r^0) \neq 0&amp;lt;/math&amp;gt; выбирается вектор &amp;lt;math&amp;gt;\overline r^0&amp;lt;/math&amp;gt;&lt;br /&gt;
#Положим &amp;lt;math&amp;gt;p^0 = r^0&amp;lt;/math&amp;gt;&lt;br /&gt;
#Устанавливаем счетчик итераций: &amp;lt;math&amp;gt;n = 0&amp;lt;/math&amp;gt;&lt;br /&gt;
:Итерационный процесс:&lt;br /&gt;
#Находим &amp;lt;math&amp;gt;\alpha_k&amp;lt;/math&amp;gt;&lt;br /&gt;
#По найденному &amp;lt;math&amp;gt;\alpha_k&amp;lt;/math&amp;gt; вычисляем &amp;lt;math&amp;gt;s_k&amp;lt;/math&amp;gt;&lt;br /&gt;
#По найденному &amp;lt;math&amp;gt;s_k&amp;lt;/math&amp;gt; вычисляется вспомогательный коэффициент &amp;lt;math&amp;gt;\omega_k&amp;lt;/math&amp;gt;&lt;br /&gt;
#Находится новое приближение &amp;lt;math&amp;gt;x^{k + 1}&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вычисляется невязка &amp;lt;math&amp;gt;r^{k + 1}&amp;lt;/math&amp;gt;. Если выполнено условие &amp;lt;math&amp;gt;\parallel r^{k + 1} \parallel &amp;lt; \epsilon&amp;lt;/math&amp;gt;, то алгоритм завершается.&lt;br /&gt;
#Вычисляется вспомогательный коэффициент &amp;lt;math&amp;gt;\beta_k&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вычисляется новый базисный вектор: &amp;lt;math&amp;gt;p^{k + 1}&amp;lt;/math&amp;gt;&lt;br /&gt;
#Увеличивается номер итерации: &amp;lt;math&amp;gt;n = n + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
#Переход к первому шагу итерационного процесса.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
:Вычислительное ядро полностью совпадает с итерационным процессом. Подготовка к итерационному процессу в ядро не включается.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
На каждой итерации алгоритма используются:&lt;br /&gt;
# [[Скалярное произведение векторов, вещественная версия, последовательно-параллельный вариант]] x 4 раза&lt;br /&gt;
# [[Умножение плотной матрицы на вектор ]] х 2 раза&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
:Всего в вычислительном блоке алгоритма присутствует 20 трудоемких операций: 2 операции умножения матрицы на вектор, 6 скалярных произведений и 6 сложений/вычитаний векторов и 6 умножений вектора на число.&lt;br /&gt;
&lt;br /&gt;
:Каждое скалярное произведение требует &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; произведений и &amp;lt;math&amp;gt;N - 1&amp;lt;/math&amp;gt; сложение, то есть &amp;lt;math&amp;gt;2N - 1&amp;lt;/math&amp;gt; операции. Скалярных произведений всего 6 штук (включая поиск нормы), что дает нам &amp;lt;math&amp;gt;12N - 6&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
:Умножение матрицы размерности &amp;lt;math&amp;gt;N \times N&amp;lt;/math&amp;gt; на вектор эквивалентно взятию еще &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; скаляров, и так как таких операций в вычислительном ядре 2, то дополнительно имеется еще &amp;lt;math&amp;gt;2N(2N - 1)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
:Наконец, сложение или вычитание векторов требует &amp;lt;math&amp;gt;6N&amp;lt;/math&amp;gt; соотвествующих операций. Столько же требует 6 произведений вектора на число.&lt;br /&gt;
&lt;br /&gt;
:Итого: &amp;lt;math&amp;gt;2N(2N - 1) + 12N - 6 + 6N + 6N = 4N^2 + 22N - 6&amp;lt;/math&amp;gt; операций за одну итерацию. Домножая это на количество итераций &amp;lt;math&amp;gt;I&amp;lt;/math&amp;gt;, получаем итоговую сложность алгоритма: &amp;lt;math&amp;gt;I * (4N^2 + 22N - 6)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Имеются так же операции как, извлечение квадратного корня и деление вещественных чисел друг на друга, но они не принимаются в расчет, так как они не влияют на итоговый результат. Окончательно можно заключить, что последовательная сложность алгоритма эквивалента &amp;lt;math&amp;gt;O(I * N^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
[[file:BiCGStabIterations.jpg|thumb|center|800px|&amp;lt;center&amp;gt;Информационный граф.&amp;lt;/center&amp;gt;]]&lt;br /&gt;
На графе представлены связи между операциями, выполняющимися в первых трех итерациях метода. При выполнении большего, чем 3, количества итераций, структура каждой новой будет повторять структуру третьей. Связи между итерациями не представлены, т.к. они не важны для понимания параллельной структуры алгоритма. Серым обозначено перемножение чисел, красным - умножение числа на вектор&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
Основной прирост производительности параллельной версии алгоритма дает использование параллельных операций вычисления скалярного произведения, суммы векторов, а так же произведения матрицы на вектор. Каждая из операций вычисления скалярного произведения и суммы векторов, выполняемая на &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; процессорах, за счет метода сдваивания может ускориться до &amp;lt;math&amp;gt; \frac{p}{\log_2 p} &amp;lt;/math&amp;gt; раз. Ускорение же умножения матрицы на вектор может достигать &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; раз.&lt;br /&gt;
&lt;br /&gt;
Ширина и высота ЯПФ графа данного алгоритма напрямую зависит от конкретных реализаций макроопераций и входных данных.&lt;br /&gt;
&lt;br /&gt;
Для последовательно-параллельной реализации операции взятия скалярного произведения в наиболее оптимальном случае (&amp;lt;math&amp;gt;p= \sqrt N&amp;lt;/math&amp;gt;) высота будет равна &amp;lt;math&amp;gt;2 \sqrt N - 1&amp;lt;/math&amp;gt;, а ширина &amp;lt;math&amp;gt;\sqrt 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;2N&amp;lt;/math&amp;gt;, а ширина &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - это уже упомянутая длина вектора(она же ширина матрицы), а m - высота матрицы.&lt;br /&gt;
&lt;br /&gt;
Высота ЯПФ операции умножения вектора на число равна &amp;lt;math&amp;gt;\frac{N}{p}&amp;lt;/math&amp;gt;, а ширина &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Высота ЯПФ операции вычисления разности векторов = &amp;lt;math&amp;gt; \log_2 p &amp;lt;/math&amp;gt;, а ширина &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В конечном счете общую высоту ЯПФ одной итерации алгоритма можно оценить, как &amp;lt;math&amp;gt;6 \sqrt N-3 + 4N + 3 + 1 + 3\lceil \frac{N}{p} \rceil + 2 \lceil \frac{N}{p} \rceil = 6 \sqrt N + 4N + 5 \lceil \frac{N}{p} \rceil + 1&amp;lt;/math&amp;gt;, а ширину, как &amp;lt;math&amp;gt;2 \sqrt N&amp;lt;/math&amp;gt;, если не брать в рассчет проверку критерия сходимости и упрощенности первой итерации по сравнению с остальными.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
:Входные данные&lt;br /&gt;
#Матрица &amp;lt;math&amp;gt;A \in R^{N \times N}&amp;lt;/math&amp;gt; ( &amp;lt;math&amp;gt;C^{N \times N}&amp;lt;/math&amp;gt; )&lt;br /&gt;
#Вектор правой части &amp;lt;math&amp;gt;b \in R^N&amp;lt;/math&amp;gt; ( &amp;lt;math&amp;gt;C^N&amp;lt;/math&amp;gt; )&lt;br /&gt;
&lt;br /&gt;
:Выходные данные:&lt;br /&gt;
#Вектор решения СЛАУ &amp;lt;math&amp;gt;x \in R^N&amp;lt;/math&amp;gt; ( &amp;lt;math&amp;gt;C^N&amp;lt;/math&amp;gt; )&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
:BiCGSTAB хорошо зарекомендовал себя для решения систем линейных алгебраический уравнений, поскольку обладает некоторыми важными свойствами:&lt;br /&gt;
#Благодаря применению подхода Петрова-Галеркина и техники ортогонализации, он численно устойчив&lt;br /&gt;
#Не меняется вид матрицы в процессе решения&lt;br /&gt;
#Эффективен для решения систем большой размерности с разреженной матрицей, поскольку в методе самая трудоемкая операция - умножение матрицы на вектор&lt;br /&gt;
#Лучше подходит под распределенные системы, поскольку не содержит операции транспонирования матрицы&lt;br /&gt;
#Применим для решения систем с несимметричными матрицами.&lt;br /&gt;
#Вычислительная мощность: &amp;lt;math&amp;gt;N/4&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
===== Анализ на основе теста Apex-Map =====&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
Исследование масштабируемости реализации стабилизированного метода бисопряженных градиентов проводилось согласно [[Scalability methodology|методике]]  на суперкомпьютере &amp;quot;Ломоносов&amp;quot;&amp;lt;ref name=&amp;quot;Lom&amp;quot;&amp;gt;Воеводин Вл., Жуматий С., Соболев С., Антонов А., Брызгалов П., Никитенко Д., Стефанов К., Воеводин Вад. Практика суперкомпьютера «Ломоносов» // Открытые системы, 2012, N 7, С. 36-39.&amp;lt;/ref&amp;gt; [http://parallel.ru/cluster Суперкомпьютерного комплекса Московского университета].&lt;br /&gt;
&lt;br /&gt;
Набор и границы значений изменяемых [[Глоссарий#Параметры запуска|параметров запуска]] реализации алгоритма: &lt;br /&gt;
&lt;br /&gt;
*	число процессоров [2 : 16] с шагом 1;&lt;br /&gt;
*	размер матрицы [262144 : 11239424].&lt;br /&gt;
&lt;br /&gt;
В результате проведённых экспериментов был получен следующий диапазон [[Глоссарий#Эффективность реализации|эффективности реализации]] алгоритма:&lt;br /&gt;
&lt;br /&gt;
*	минимальная эффективность реализации 60,00%;&lt;br /&gt;
*	максимальная эффективность реализации 98,33%.&lt;br /&gt;
&lt;br /&gt;
На следующих рисунках приведены графики [[Глоссарий#Производительность|производительности]] и эффективности выбранной реализации стабилизированного метода бисопряженных градиентов в зависимости от изменяемых параметров запуска.&lt;br /&gt;
&lt;br /&gt;
[[file:Масштабируемость параллельной реализации BiCGSTAB Производительность.png|thumb|center|700px|Параллельная реализация стабилизированного метода бисопряженных градиентов. Изменение производительности в зависимости от числа процессоров и размера матрицы.]]&lt;br /&gt;
[[file:Масштабируемость параллельной реализации BiCGSTAB эффективность.png|thumb|center|700px|Параллельная реализация стабилизированного метода бисопряженных градиентов. Изменение эффективности в зависимости от числа процессоров и размера матрицы.]]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/LLNL/hypre/blob/master/src/krylov/HYPRE_bicgstab.c Исследованная параллельная реализация на языке C]&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
* Параллельная реализация алгоритма, предложенная MIT: [http://ab-initio.mit.edu/~meep/meep/src/bicgstab.cpp MIT BiCGSTAB]&lt;br /&gt;
* Параллельная реализация алгоритма в бесплатной библиотеке, поддерживающей MPI и OpenMP, HYPRE: [http://acts.nersc.gov/hypre/ Официальная страница] [https://github.com/LLNL/hypre/blob/master/src/krylov/bicgstab.c Исходный код]&lt;br /&gt;
* Параллельная реализация алгоритма на CUDA в условно бесплатной библиотеке [https://developer.nvidia.com/amgx/ NVIDIA AmgX]&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;/div&gt;</summary>
		<author><name>Algoman</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%D1%86%D0%B0:%D0%90%D0%BB%D0%B5%D0%BA%D1%81%D0%B0%D0%BD%D0%B4%D1%80%D0%B0/%D0%9C%D0%B5%D1%82%D0%BE%D0%B4_%D0%B2%D1%81%D1%82%D1%80%D0%B5%D1%87%D0%B8_%D0%BF%D0%BE%D1%81%D0%B5%D1%80%D0%B5%D0%B4%D0%B8%D0%BD%D0%B5&amp;diff=18938</id>
		<title>Участница:Александра/Метод встречи посередине</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D1%86%D0%B0:%D0%90%D0%BB%D0%B5%D0%BA%D1%81%D0%B0%D0%BD%D0%B4%D1%80%D0%B0/%D0%9C%D0%B5%D1%82%D0%BE%D0%B4_%D0%B2%D1%81%D1%82%D1%80%D0%B5%D1%87%D0%B8_%D0%BF%D0%BE%D1%81%D0%B5%D1%80%D0%B5%D0%B4%D0%B8%D0%BD%D0%B5&amp;diff=18938"/>
		<updated>2016-11-22T11:54:07Z</updated>

		<summary type="html">&lt;p&gt;Algoman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Algoman}}&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Метод встречи посередине&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(\sqrt n\log(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;O(\log(n))&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;\log(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;
Метод &amp;quot;Встреча посередине&amp;quot; криптоанализа блочных шифров был впервые предложен в 1977 году Уитфилдом Диффи и Мартином Хеллманом &amp;lt;ref&amp;gt;(June 1977) «Exhaustive Cryptanalysis of the NBS Data Encryption Standard». Computer 10 (6): 74–84. DOI:10.1109/C-M.1977.217750&amp;lt;/ref&amp;gt;. Встреча посередине используется для ускорения перебора ключей шифра за счёт увеличения требуемой памяти. Метод применим в случае каскадного построения сложного шифра из нескольких простых, другими словами, в случае последовательного применения шифрующих преобразований на разных ключах к блокам открытого текста.&lt;br /&gt;
&lt;br /&gt;
В качестве примера шифра, поддающегося атаке &amp;quot;встреча посередине&amp;quot; можно привести криптоалгоритм 2DES, являющийся модификацией шифра DES. В 2DES открытый текст шифруется дважды алгоритмом DES на двух разных 56-битных ключах. Однако из-за атаки &amp;quot;встреча посередине&amp;quot; сложность перебора двойного ключа (112 бит) шифра 2DES составляет &amp;lt;math&amp;gt;2^{57}&amp;lt;/math&amp;gt; вместо ожидаемых &amp;lt;math&amp;gt;2^{112}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Исходные данные:&#039;&#039;&#039; открытый текст &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;, шифртекст &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Алгоритм зашифрования — композиция двух преобразований &amp;lt;math&amp;gt;T_1(x,k_1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;T_2(x,k_2)&amp;lt;/math&amp;gt;, т.е. &amp;lt;math&amp;gt;y=T_2(T_1(x,k_1),k_2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм расшифрования — &amp;lt;math&amp;gt;y=T_1^{-1}(T_2^{-1}(x,k_2),k_1)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вычисляемые данные:&#039;&#039;&#039; ключи шифрования &amp;lt;math&amp;gt;k_1 \in K_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;k_2 \in K_2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;K_1, K_2&amp;lt;/math&amp;gt; — множества возможных ключей.&lt;br /&gt;
&lt;br /&gt;
Трудоёмкость полного перебора всех возможных пар &amp;lt;math&amp;gt;k_1,k_2&amp;lt;/math&amp;gt; составляет в среднем &amp;lt;math&amp;gt;\frac{|K_1||K_2|}{2}&amp;lt;/math&amp;gt;, а в худшем случае &amp;lt;math&amp;gt;|K_1||K_2|&amp;lt;/math&amp;gt;. Однако используя дополнительную память, можно сократить перебор.&lt;br /&gt;
&lt;br /&gt;
Предположим, что открытый текст &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; и шифртекст &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; однозначно определяют ключи &amp;lt;math&amp;gt;k_1,k_2&amp;lt;/math&amp;gt;. Составим две таблицы:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
z_1 &amp;amp; =T_1(x,k_1^1) &amp;amp; z_1^&#039; &amp;amp;=T_2^{-1}(x,k_2^1)\\\\&lt;br /&gt;
z_2 &amp;amp; =T_1(x,k_1^2) &amp;amp; z_2^&#039; &amp;amp; =T_2^{-1}(x,k_2^2)\\&lt;br /&gt;
... &amp;amp; .................  &amp;amp; ... &amp;amp; .................... \\&lt;br /&gt;
z_{|K_1|} &amp;amp; =T_1(x,k_1^{|K_1|}) &amp;amp; z_{|K_1|}^&#039; &amp;amp; =T_2^{-1}(x,k_2^{|K_1|})&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для всех &amp;lt;math&amp;gt;k_1^i \in K_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;k_2^j \in K_2&amp;lt;/math&amp;gt;. Далее таблицы объединяются и сортируются по значениям &amp;lt;math&amp;gt;z_i,z_j^&#039;&amp;lt;/math&amp;gt;. Индексы &amp;lt;math&amp;gt;i,j&amp;lt;/math&amp;gt;, при которых &amp;lt;math&amp;gt;z_i=z_j^&#039;&amp;lt;/math&amp;gt;, однозначно определяют искомую пару ключей &amp;lt;math&amp;gt;k_1=k_1^i,k_2=k_2^j&amp;lt;/math&amp;gt;. Для нахождения такой пары достаточно просмотреть отсортированную таблицу один раз.&lt;br /&gt;
&lt;br /&gt;
Если же пара открытый текст/шифртекст определяет ключ не единственном образом, то выходом алгоритма будет некоторое множество пар &amp;lt;math&amp;gt;k_1,k_2&amp;lt;/math&amp;gt;, одна из которых является истинным ключом. Для выбора истинного ключа достаточно проверить ключи из полученного множества на других парах открытый текст/шифртекст.&lt;br /&gt;
&lt;br /&gt;
==== Оптимизации ====&lt;br /&gt;
&lt;br /&gt;
1. От генерации второй таблицы со значениями &amp;lt;math&amp;gt;z_j^&#039;&amp;lt;/math&amp;gt; можно отказаться, перебирая ключи &amp;lt;math&amp;gt;k_2^j&amp;lt;/math&amp;gt; до того момента, когда значение &amp;lt;math&amp;gt;z_j^&#039;&amp;lt;/math&amp;gt; совпадёт с одним из значений &amp;lt;math&amp;gt;z_i&amp;lt;/math&amp;gt;. В таком случае опробование ключей &amp;lt;math&amp;gt;k_2^j&amp;lt;/math&amp;gt; в среднем сократится вдвое. Также вдвое сократится объём используемой памяти. Для нахождения совпадающего значения в отсортированном массиве можно применить бинарный поиск.&lt;br /&gt;
&lt;br /&gt;
2. Вместо сортировки таблицы со значениями &amp;lt;math&amp;gt;z_i&amp;lt;/math&amp;gt; и последующего бинарного поиска можно использовать хэш-таблицу.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
В случае использования хэш-таблицы достаточно большого размера основную сложность алгоритма составляет опробование ключей &amp;lt;math&amp;gt;k_1,k_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
Одним из самых трудоёмких шагов также оказывается сортировка таблицы.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Как видно из описания, атака &amp;quot;встреча посередине&amp;quot; использует (или может использовать в качестве оптимизации) следующие алгоритмы:&lt;br /&gt;
&lt;br /&gt;
1. Алгоритм зашифрования/расшифрования&lt;br /&gt;
&lt;br /&gt;
2. Алгоритм сортировки&lt;br /&gt;
&lt;br /&gt;
3. Алгоритмы поиска, вставки в хэш-таблицу&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Далее приводится последовательность действий для варианта алгоритма с генерацией одной таблицы значений &amp;lt;math&amp;gt;z_i&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
1. Вычислить таблицу &amp;lt;math&amp;gt;z_i&amp;lt;/math&amp;gt;, записывая значения в порядке вычисления или используя хэш-таблицу&lt;br /&gt;
&lt;br /&gt;
2. В случае записи значений в порядке вычисления отсортировать массив&lt;br /&gt;
&lt;br /&gt;
3. Опробовать ключи &amp;lt;math&amp;gt;k_2^j&amp;lt;/math&amp;gt;, ища совпадения с таблицей значений &amp;lt;math&amp;gt;z_j^&#039;&amp;lt;/math&amp;gt;. Для нахождения совпадения использовать поиск по хэш-таблице (если она есть) или бинарный поиск&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
Всюду далее считаем, что алгоритм не прекращает работу при нахождении первого совпадения, а ищет все совпадения.&lt;br /&gt;
&lt;br /&gt;
1. Сложность вычисления таблиц значений &amp;lt;math&amp;gt;z_i,z_j^&#039;&amp;lt;/math&amp;gt; составит &amp;lt;math&amp;gt;O(|K_1|+|K_2|)&amp;lt;/math&amp;gt; операций опробования &lt;br /&gt;
&lt;br /&gt;
2. Объединение таблиц и их сортировка будет иметь сложность &amp;lt;math&amp;gt;O((|K_1|+|K_2|)\log(|K_1|+|K_2|))&amp;lt;/math&amp;gt; (например, при сортировке слиянием).&lt;br /&gt;
&lt;br /&gt;
3. Сложность бинарного поиска в отсортированном массиве — &amp;lt;math&amp;gt;O(log_2(|K_1|))&amp;lt;/math&amp;gt; для каждого поиска&lt;br /&gt;
&lt;br /&gt;
4. Сложность поиска в достаточно большой хэш-таблице составит &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt; для каждого поиска&lt;br /&gt;
&lt;br /&gt;
Итого асимптотическая сложность алгоритма:&lt;br /&gt;
&lt;br /&gt;
1. С генерацией двух таблиц — &amp;lt;math&amp;gt;O(|K_1|+|K_2|) + O((|K_1|+|K_2|)\log(|K_1|+|K_2|)) + O(|K_1|+|K_2|)=O((|K_1|+|K_2|)\log(|K_1|+|K_2|))&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. C генерацией одной таблицы, сортировкой и бинарным поиском — &amp;lt;math&amp;gt;O(|K_1|) + O((|K_1|)\log(|K_1|)) + O(|K_2|\log_2(|K_1|))=O(max(|K_1|,|K_2|)\log(|K_1|))&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3. C генерацией одной (достаточно большой) хэш-таблицы — &amp;lt;math&amp;gt;O(|K_1|) + O(|K_2|)=O(|K_1|+|K_2|)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть n - количество всевозможных пар &amp;lt;math&amp;gt;k_1,k_2&amp;lt;/math&amp;gt; и пусть &amp;lt;math&amp;gt;|K_1|=|K_2|&amp;lt;/math&amp;gt;. В этом случае &amp;lt;math&amp;gt;|K_1|=|K_2|=\sqrt n&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Тогда сложность алгоритма в первых двух пунктах составляет &amp;lt;math&amp;gt;O(\sqrt n\log(n))&amp;lt;/math&amp;gt;, в третьем — &amp;lt;math&amp;gt;O(\sqrt n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
&lt;br /&gt;
Опишем информационный граф алгоритма. На вход подаётся открытый (Open) и закрытый (Close), т.е. зашифрованный, текст. Далее открытый текст шифруется (Enc) на ключах &amp;lt;math&amp;gt;k_1^i&amp;lt;/math&amp;gt;, а зашифрованный расшифровывается (Dec) на ключах &amp;lt;math&amp;gt;k_2^j&amp;lt;/math&amp;gt;. Далее полученные криптограммы сравниваются (Cmp) и все ключи, на которых они совпали, являются выходом алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[file:meet.png|thumb|center|900px|Рисунок 1. Граф алгоритма c отображением входных и выходных данных. Open — открытый текст, Close — шифртекст, Enc — операция зашифрования, Dec — операция расшифрования, Cmp — операция сравнения, Keys — вычисленные ключи]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Как видно из информационного графа, для реализации атаки &amp;quot;встреча посередине&amp;quot; в параллельном варианте потребуются выполнение следующих двух ярусов (в предположении, что &amp;lt;math&amp;gt;|K_1|=|K_2|&amp;lt;/math&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
1. &amp;lt;math&amp;gt;\sqrt n&amp;lt;/math&amp;gt; зашифрований и столько же расшифрований&lt;br /&gt;
&lt;br /&gt;
2. &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; сравнений&lt;br /&gt;
&lt;br /&gt;
Таким образом, высота ЯПФ составляет 2, ширина - &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вход:&#039;&#039;&#039;&lt;br /&gt;
На вход подаётся открытый текст &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; и шифртекст &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;, а также алгоритм зашифрования/расшифрования. В случае блочного шифра открытым текстом и шифртекстом является последовательность блоков. Для атаки &amp;quot;встреча посередине&amp;quot;, как правило, берётся один блок для максимального ускорения операций зашифрования и расшифрования.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выход:&#039;&#039;&#039;&lt;br /&gt;
Результатом работы алгоритма является множество пар &amp;lt;math&amp;gt;k_1^i,k_2^j&amp;lt;/math&amp;gt;, для которых нашлись совпадения. Только одна из пар является настоящим ключом. Чтобы отсеять лишние, необходимо проверить все пары на блоках открытого и шифрованного текста, которые в алгоритме не использовались.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
Соотношением последовательной и параллельной сложности алгоритма является &amp;lt;math&amp;gt;O(\sqrt n\log(n))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Будем считать, что размер входных данных (открытый текст и шифртекст) совпадает с размером ключа (на практике это сравнимые величины), а сортировка слиянием делит массивы пополам. Тогда вычислительная мощность алгоритма — &amp;lt;math&amp;gt;O(\sqrt n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Дуги информационного графа, исходящие из вершин зашифрования и расшифрования, образуют пучки мощности &amp;lt;math&amp;gt;\sqrt n&amp;lt;/math&amp;gt;, т.е. из каждой такой вершины выходит &amp;lt;math&amp;gt;\sqrt 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;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
Исследование масштабируемости реализации алгоритма проводилось на суперкомпьютере &amp;quot;Ломоносов&amp;quot;&amp;lt;ref name=&amp;quot;Lom&amp;quot;&amp;gt;Воеводин Вл., Жуматий С., Соболев С., Антонов А., Брызгалов П., Никитенко Д., Стефанов К., Воеводин Вад. Практика суперкомпьютера «Ломоносов» // Открытые системы, 2012, N 7, С. 36-39.&amp;lt;/ref&amp;gt; [http://parallel.ru/cluster Суперкомпьютерного комплекса Московского университета]. Изменяемые параметры запуска:&lt;br /&gt;
* Размер ключа – от 8 до 20 бит с шагом 1&lt;br /&gt;
* Число ядер – от 1 до 8 (значения являются степенью числа 2)&lt;br /&gt;
Ниже представлен график зависимости [[Глоссарий#Производительность|производительности]] от числа ядер и размера ключа (размер задачи – экспоненциальная функция от размера ключа). Для измерения производительности в качестве базовой операции используется операция опробования ключа и время в секундах. Количество арифметических операций, содержащихся в операции опробования, может быть разным в зависимости от используемого алгоритма шифрования.&lt;br /&gt;
[[File:Масштабируемость.jpg|thumb|center|900px|Рисунок 2. Масштабируемость реализации алгоритма]]&lt;br /&gt;
&lt;br /&gt;
Как видно из графика, производительность почти не изменяется в зависимости от размера задачи, в то время как зависимость производительности от числа ядер визуально близка к линейной. Это связано с тем, что алгоритм содержит большое количество независимых операций опробования ключа, синхронизация между параллельно выполняющимися опробованиями не требуется.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/AlBatarina/Super2016/blob/master/meet_in_the_middle/meet.c Исследованная параллельная реализация на языке C]&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Одна из реализаций атаки &amp;quot;встреча посередине&amp;quot; с использованием хэш-таблицы представлена в свободном доступе по ссылке [https://gist.github.com/dchest/1062437 github]&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;/div&gt;</summary>
		<author><name>Algoman</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:Noite/EM-%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8&amp;diff=18797</id>
		<title>Участник:Noite/EM-алгоритм кластеризации</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:Noite/EM-%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8&amp;diff=18797"/>
		<updated>2016-11-21T13:16:07Z</updated>

		<summary type="html">&lt;p&gt;Algoman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = EM-алгоритм кластеризации&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(iter * N * M^2 * K)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;N * M + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(iter * M^2 * K)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(iter * N)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Автор описания: [[Участник:Noite|Зинченко Д.А.]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритма =&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
В задачах оптимизации EM-алгоритмом называют итеративную процедуру поиска численного значения экстремума какой-либо функции. В частности, в статистике этот алгоритм используется для оценки максимального правдоподобия. Впервые название EM-алгоритм было предложено в 1977 году&amp;lt;ref&amp;gt;A. Dempster, N. Laird and D. Rubin. Maximum likelihood estimation from incomplete data. – Journal of the Royal Statistical Society, Series B, 1977, vol. 39, p. 1-38.&amp;lt;/ref&amp;gt;, однако его идеи были описаны и раньше&amp;lt;ref name=korolev&amp;gt;В.Ю.Королёв. ЕМ-алгоритм, его модификации и их применение к задаче разделения смесей вероятностных распределений.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
EM-алгоритм применяется для решения задач двух типов &amp;lt;ref name=korolev/&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
# Анализ неполных данных (данных с пропусками). &lt;br /&gt;
# Оценка максимального правдоподобия в случае, если функцию правдоподобия трудно исследовать аналитически. В этом случае введение набора скрытых переменных может существенно упростить задачу.&lt;br /&gt;
&lt;br /&gt;
Задача кластеризации относится к задачам второго типа. В данной статье рассматривается следующая постановка задачи кластеризации:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;Дано множество из N объектов, каждый из которых представляет собой точку в M-мерном метрическом пространстве. Каждому измерению пространства соответствует некоторое свойство объекта. Необходимо разбить это множество на K подмножеств (кластеров) так, чтобы, чтобы элементы каждого подмножества существенно отличались по свойствам от элементов других подмножеств.&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Использование алгоритма EM подразумевает следующее &#039;&#039;предположение об объектах&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
Пусть объекты, которые необходимо разбить на кластеры, появляются случайным образом и независимо друг от друга согласно вероятностному распределению, равному смеси (линейной комбинации) распределений кластеров. В данной статье в дальнейшем будет считаться, что распределение каждого кластера является многомерным нормальным распределением с произвольной матрицей ковариации - наиболее часто используемое предположение.&lt;br /&gt;
&lt;br /&gt;
Тогда каждый объект принадлежит каждому кластеру, но с разной вероятностью. EM-алгоритм итеративно оценивает параметры распределений кластеров, максимизируя логарифмическую функцию максимального правдоподобия. После окончания работы алгоритма объект будет отнесен к кластеру, вероятность принадлежности которому максимальна. Вводимый набор скрытых переменных для каждого объекта - вероятности того, что объект принадлежит каждому из кластеров.&lt;br /&gt;
&lt;br /&gt;
Итерация алгоритма состоит из двух последовательных шагов.&lt;br /&gt;
&lt;br /&gt;
# (Expectation) Вычисляются новые ожидаемые значения скрытых переменных.&lt;br /&gt;
# (Maximization) Решается задача максимизации правдоподобия: По текущим значениям скрытых переменных обновляются параметры распределений для кластеров: математическое ожидание, дисперсия и вероятность появления объектов из кластера.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Используемые обозначения:&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - количество объектов, &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество параметров объекта&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma_{n,k}&amp;lt;/math&amp;gt; - значения скрытых переменных&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;N_{k}&amp;lt;/math&amp;gt; - количество элементов отнесенных к кластеру &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x_{1},...,x_N&amp;lt;/math&amp;gt; - объекты&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Параметры распределений:&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;w_{1},...,w_{K}&amp;lt;/math&amp;gt; - вероятности появления объектов из кластеров (веса кластеров), &amp;lt;math&amp;gt;\sum_{k=1}^Kw_{k}=1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\mu_{1},...,\mu_{K}&amp;lt;/math&amp;gt; - центры гауссиан кластеров&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\Sigma_{1},...,\Sigma_{K}&amp;lt;/math&amp;gt; - матрицы ковариации гауссиан кластеров, каждая матрица имеет размерность &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;x&amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Смесь распределений:&#039;&#039;&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt; P(x) = \sum_{j=1}^Kw_jp(x|\mu_{j}, \Sigma_{j})&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Цель алгоритма - вычислить параметры распределений, максимизирующих логарифм функции правдоподобия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;\ln P(x|w,\mu,\Sigma)= \sum_{n=1}^N \ln \{ \sum_{k=1}^K w_{k}p(x_{n}|\mu_{k},\Sigma_{k})\}&amp;lt;/math&amp;gt;.&amp;lt;/center&amp;gt;  &lt;br /&gt;
&lt;br /&gt;
* В начале работы алгоритма задаются параметры начального приближения:&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;w_{i} = 1/K, \mu_{i} = random(x_{j}), i=1..K, j=1..N&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;\Sigma_{j,j}^{k}=\frac{1}{NK}\sum_{i=1}^N(x_{i,j} - \mu_{k,j})^2, k=1..K, j=1..M&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Поскольку от начального приближения может сильно зависеть результат работы алгоритма, вместо инициализации кластеров случайными центрами, равными весами и диагональными матрицами ковариации, как в приведенных формулах, часто применяют другие способы (подробнее - в [[#Особенности реализации последовательного алгоритма | особенностях реализации]])&#039;&#039;&lt;br /&gt;
* Далее итеративно выполняется следующая пара процедур:&lt;br /&gt;
** E-шаг: используя текущее значение параметров &amp;lt;math&amp;gt;w_{1},...,w_{k};\mu_{1},...,\mu_{k};\Sigma^{1},...,\Sigma^{k}&amp;lt;/math&amp;gt;, вычисляем значение вектора скрытых переменных &amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt;:&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;\gamma_{n,k}=\frac{w_{k}p(x_{n}|\mu_{k},\Sigma^{k})}{\sum_{j=1}^K w_{j}p(x_{n}|\mu_{j},\Sigma^{j})}, &amp;lt;/math&amp;gt; знаменатель дроби - нормировочный коэффициент&amp;lt;/center&amp;gt;&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;p(x|\mu,\Sigma)=\frac{1}{{(2\pi)}^{\frac{N}{2}}\sqrt{|\Sigma|}}exp\biggl\{-\frac{1}{2}{(x-\mu)}^T{\Sigma}^{-1}(x-\mu)\biggr\}&amp;lt;/math&amp;gt; - плотность &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;-мерного нормального распределения&amp;lt;/center&amp;gt;&lt;br /&gt;
** М-шаг: переоценка параметров по текущим значениям скрытых переменных для &amp;lt;math&amp;gt;k = 1..K&amp;lt;/math&amp;gt;:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;\mu^{new}_{k}=\frac{1}{N_{k}}\sum_{n=1}^N \gamma_{n,k}x_{n}&amp;lt;/math&amp;gt;,&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;\Sigma_{new}^{k}=\frac{1}{N_{k}}\sum_{n=1}^N \gamma_{n,k} (x_{n}-\mu_{k}^{new})(x_{n}-\mu_{k}^{new})^{T}&amp;lt;/math&amp;gt;,&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;w_{k}^{new}=\frac{N_{k}}{N}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;N_{k}=\sum_{n=1}^N \gamma_{n,k}&amp;lt;/math&amp;gt;.&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В EM алгоритме используется один из следующих критериев остановки:&lt;br /&gt;
*Норма разности векторов скрытых переменных на текущей итерации не превышает заданную константу &lt;br /&gt;
*Прошествие заданного количества итераций&lt;br /&gt;
*Изменение логарифмического правдоподобия меньше заданной константы.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро алгоритма состоит из двух шагов, повторяющихся каждую итерацию:&lt;br /&gt;
*Обновление скрытых переменных на основе текущих параметров распределений&lt;br /&gt;
*Обновление параметров кластеров: весов, центров и матриц ковариации&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как записано в [[#Вычислительное ядро алгоритма|описании вычислительного ядра алгоритма]], основную часть алгоритма составляют итеративно проводимые макрооперации: Expectation шаг - вычисление новых значений скрытых переменных, Maximization шаг - обновление параметров кластеров. Макроструктура алгоритма представлена на рисунке 1:&lt;br /&gt;
[[file:EM_macro.png|thumb|center|600px|Рисунок 1: Макроструктура EM-алгоритма]]&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Примерная схема реализации EM алгоритма с предварительной обработкой матриц ковариации:&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Инициализировать веса и центры кластеров;&lt;br /&gt;
Инициализировать матрицы ковариации;&lt;br /&gt;
&lt;br /&gt;
// Основной цикл&lt;br /&gt;
Пока условие остановки не выполнено&lt;br /&gt;
    // E-шаг&lt;br /&gt;
    В цикле для каждого кластера&lt;br /&gt;
        Вычислить определитель матрицы ковариации Sigma;&lt;br /&gt;
        Вычислить обратную матрицу матрице Sigma;&lt;br /&gt;
    В цикле для каждого объекта&lt;br /&gt;
        В цикле для каждого кластера&lt;br /&gt;
            Вычислить и запомнить p(x | mu, Sigma) для текущего объекта и кластера;&lt;br /&gt;
        Просуммировать вычисленные p(x | mu, Sigma);&lt;br /&gt;
        В цикле для каждого кластера&lt;br /&gt;
            Обновить скрытые переменные gamma;&lt;br /&gt;
    // M-шаг&lt;br /&gt;
    Обновить веса w;&lt;br /&gt;
    Обновить центры кластеров mu;&lt;br /&gt;
    Обновить матрицы ковариации Sigma;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Количество итераций алгоритма зависит от условия остановки, поэтому будем рассматривать сложность одной итерации.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Шаг E&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Сложность вычисления определителя произвольной матрицы ковариации &amp;lt;math&amp;gt;\Sigma&amp;lt;/math&amp;gt; методом Гаусса - &amp;lt;math&amp;gt;O(M^3)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Сложность вычисления матрицы, обратной произвольной матрице ковариации &amp;lt;math&amp;gt;\Sigma&amp;lt;/math&amp;gt; методом Гаусса - &amp;lt;math&amp;gt;O(M^3)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Сложность предварительного вычисления определителей и обратных матриц матрицам ковариации - &amp;lt;math&amp;gt;O(K * M^3)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С учетом заранее вычисленных определителей и обратных матриц сложность вычисления &amp;lt;math&amp;gt;p(x | \mu,\Sigma)&amp;lt;/math&amp;gt; составит: &amp;lt;math&amp;gt;O(M^2)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Суммарно сложность шага E составит &amp;lt;math&amp;gt;O(N * M^2 * K + K * M^3)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Шаг M&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Сложность обновления весов кластеров &amp;lt;math&amp;gt;O(K * N)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Сложность обновления центров кластеров &amp;lt;math&amp;gt;O(K * M * N)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Сложность обновления одной матрицы ковариации &amp;lt;math&amp;gt;O(N * M)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Сложность обновления всех матриц ковариации &amp;lt;math&amp;gt;O(K * M * N)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Суммарно сложность шага M алгоритма - &amp;lt;math&amp;gt;O(K * M * N)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Таким образом, сложность одной итерации EM алгоритма для псевдокода, указанного в предыдущем разделе, составит &amp;lt;math&amp;gt;O(K * M^2 * N + K * M^3 + K * M * N)&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
В предположении, что размерность объектов много меньше их количества &amp;lt;math&amp;gt;M &amp;lt;&amp;lt; N&amp;lt;/math&amp;gt; получим сложность итерации &amp;lt;math&amp;gt;O(K * M^2 * N)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что вычисление определителя и обратной матрицы к произвольной матрице ковариации составляет большу́ю часть работы шага E и существенно влияет на его сложность. Поэтому эти вычисления проведены заранее - вынесены за основной цикл шага E&amp;lt;ref name=ParallelEMComparissonGraphLab&amp;gt;Henggang Cui, Jinliang Wei, Wei Dai. Parallel Implementation of Expectation-Maximization for Fast Convergence - School of Computer Science, Carnegie Mellon University. [https://users.ece.cmu.edu/~hengganc/archive/report/final.pdf]&amp;lt;/ref&amp;gt;. Помимо этого сложность этих вычислений можно сократить еще сильнее, если ввести ограничения структуру матрицы ковариации &amp;lt;math&amp;gt;\Sigma&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Наиболее часто используемым ограничением, позволяющим эффективно распараллеливать алгоритм&amp;lt;ref&amp;gt;Вячеслав Орешков. EМ — масштабируемый алгоритм кластеризации [https://basegroup.ru/community/articles/em]&amp;lt;/ref&amp;gt;, является предположение, что матрица ковариации имеет диагональную форму. Тогда вычисление её определителя и обратной матрицы имеет сложнось &amp;lt;math&amp;gt;O(M)&amp;lt;/math&amp;gt;, а суммарная сложность шага E и сложность всей итерации составит &amp;lt;math&amp;gt;O(K * M * N)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
Макроструктура алгоритма представлена на рисунке 1 (см. [[#Макроструктура алгоритма|раздел 1.4]] статьи).&lt;br /&gt;
&lt;br /&gt;
На рисунке 2 представлена схема вычислений E-шага алгоритма для одного объекта: для объекта &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; и параметров &amp;lt;math&amp;gt;w_{j}, \mu_{j}, \Sigma_{j}, j=1..K&amp;lt;/math&amp;gt; по формулам [[#Математическое описание алгоритма|раздела 1.2]] вычисляются ненормированные значения скрытых переменных &amp;lt;math&amp;gt;g_{j}&amp;lt;/math&amp;gt;, нормировочный коэффициент &#039;&#039;normСoeff&#039;&#039;, и получаются итоговые значения &amp;lt;math&amp;gt;\gamma_{i,j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[file:EM_Expectation_step.png|thumb|center|400px|Рисунок 2: E-шаг EM алгоритма для одного объекта]]&lt;br /&gt;
&lt;br /&gt;
На рисунке 3 представлена схема вычислений E-шага алгоритма для всех объектов: для объекта &amp;lt;math&amp;gt;x_{j}&amp;lt;/math&amp;gt; и параметров-векторов &amp;lt;math&amp;gt;w, \mu, \Sigma&amp;lt;/math&amp;gt; по формулам [[#Математическое описание алгоритма|раздела 1.2]] вычисляются значения скрытых переменных. &amp;lt;math&amp;gt;E_{i}, i=1..N&amp;lt;/math&amp;gt; - маркооперации, E-шаги для соответствующих объектов.&lt;br /&gt;
&lt;br /&gt;
[[file:EM_Expectation_step_all.png|thumb|center|400px|Рисунок 3: E-шаг EM алгоритма для всех объектов]]&lt;br /&gt;
&lt;br /&gt;
На рисунке 4 представлена схема вычислений M-шага алгоритма для одного кластера: для объектов &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; и скрытых переменных &amp;lt;math&amp;gt;\gamma_{i,j}&amp;lt;/math&amp;gt;, соответствующих степени принадлежности этих объектов кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;, согласно формулам шага M [[#Математическое описание алгоритма|раздела 1.2]] вычисляется нормировочный коэффициент &amp;lt;math&amp;gt;N_{j}&amp;lt;/math&amp;gt; и параметры этого кластера: вес &amp;lt;math&amp;gt;w_{j}^{new}&amp;lt;/math&amp;gt;, матрица ковариации &amp;lt;math&amp;gt;\Sigma_{j}^{new}&amp;lt;/math&amp;gt; и центр кластера &amp;lt;math&amp;gt;\mu_{j}^{new}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[file:EM_Maximization_step.png|thumb|center|400px|Рисунок 4: M-шаг EM алгоритма для одного кластера]]&lt;br /&gt;
&lt;br /&gt;
На рисунке 5 представлена схема вычислений M-шага алгоритма для всех кластеров. &amp;lt;math&amp;gt;M_{j}, j=1..K&amp;lt;/math&amp;gt; соответствует макрооперации - M-шагу для соответствующего кластера и скрытых переменных.&lt;br /&gt;
&lt;br /&gt;
[[file:EM_Maximization_step_all.png|thumb|center|400px|Рисунок 5: M-шаг EM алгоритма для всех кластеров]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Из схем вычислений шагов E и M шагов алгоритма, приведенным в [[#Информационный граф|предыдущем разделе]], видно, что если размерность матрицы ковариации небольшая (тогда вычисление определителя и обратной матрицы матрице ковариации не является трудоемкой операцией), обе макрооперации EM алгоритма можно распараллеливать как по кластерам, так и по объектам.&lt;br /&gt;
&lt;br /&gt;
Как правило количество кластеров, на которые нужно разбить объекты, несравнимо меньше количества объектов, поэтому распараллеливание в большинстве существующих реализаций происходит по объектам: обработка объектов по возможности равномерно распределяются по кластерам. Теоретически (если считать передачу данных между процессорами мгновенной) при наличии неограниченного числа процессоров сложность алгоритма составит &amp;lt;math&amp;gt;O(M^2 * K)&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;K&amp;lt;/math&amp;gt; - количество кластеров;&lt;br /&gt;
* Значения координат объектов &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; - &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; объектов с &amp;lt;math&amp;gt;M&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;N * M&amp;lt;/math&amp;gt; вещественных чисел (если координаты объектов - вещественные числа), &amp;lt;math&amp;gt;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;N&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;N&amp;lt;/math&amp;gt; целых неотрицательных чисел.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
=== Преимущества и недостатки ===&lt;br /&gt;
EM-алгоритм обладает следующими преимуществами и недостатками&amp;lt;ref&amp;gt;EM алгоритм, его модификации и обобщения. machinelearning.ru [http://www.machinelearning.ru/wiki/index.php?title=EM-%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC]&amp;lt;/ref&amp;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;
&#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;
[[file:DifferentCovariance.png|thumb|center|800px|Рисунок 6: Влияние структуры матрицы ковариации на форму кластеров для двумерного случая. a) - матрицы ковариации являются диагональными, b) - матрицы ковариации произвольны. &amp;lt;ref&amp;gt;Mathworks: Clustering Using Gaussian Mixture Models [http://www.mathworks.com/help/stats/clustering-using-gaussian-mixture-models.html]&amp;lt;/ref&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Рисунок 6 наглядно показывает, что при диагональной форме матриц ковариации полуоси эллипса (в общем случае - эллипсоида), соответствующего распределению объектов, отнесенных кластеру, параллельны осям координат объектов. В противном случае полуоси могут располагаться произвольным образом.&lt;br /&gt;
&lt;br /&gt;
=== Общие свойства ===&lt;br /&gt;
[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]] EM алгоритма равна &amp;lt;math&amp;gt;M * K * it&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - размерность объекта, &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; - количество кластеров, а &amp;lt;math&amp;gt;it&amp;lt;/math&amp;gt; - количество итераций. &lt;br /&gt;
&lt;br /&gt;
EM-алгоритм является итерационным, и число итераций в общем случае не фиксировано: оно зависит от условий остановки, начальных приближений и расположения объектов. Поэтому этот алгоритм &#039;&#039;недетерминированный&#039;&#039;. По тем же причинам EM-алгоритм является &#039;&#039;неустойчивым&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
=== Инициализация параметров распределений ===&lt;br /&gt;
Наиболее распространены 3 способа инициализации центров распределений для EM алгоритма:&lt;br /&gt;
# центр распределения совпадает со случайно выбранным объектом &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt;&lt;br /&gt;
# все наблюдения распределяются по кластерам случайным образом, а затем для каждого кластера пересчитывается цент соответствующего распределения&lt;br /&gt;
# центры кластеров получаются в результате работы алгоритма k-means. Использование такой инициализации оправдано тем, что k-means требует меньших вычислительных затрат и быстрее сходится&amp;lt;ref&amp;gt;EM алгоритм (пример) machinelearning.ru [http://www.machinelearning.ru/wiki/index.php?title=EM_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_(%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80])&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;
Многие статьи&amp;lt;ref name=FREERIDE&amp;gt;Leonid Glimcher, Gagan Agrawal. Parallelising EM Algorithm on a Cluster of SMPs [http://web.cse.ohio-state.edu/~agrawal/allpapers/europar04.pdf]&amp;lt;/ref&amp;gt;&amp;lt;ref name=CV&amp;gt;López-de-Teruel P. E., García J. M., Acacio; The Parallel EM Algorithm and its Applications in Computer Vision [http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.4.8470&amp;amp;rep=rep1&amp;amp;type=pdf]&amp;lt;/ref&amp;gt;&amp;lt;ref name=MULTITHREAD&amp;gt;Sharon X. Lee, Kaleb L. Leemaqz, Geoffrey J. McLachlan. A simple multithreaded implementation of the EM algorithm for mixture models [https://arxiv.org/pdf/1606.02054.pdf]&amp;lt;/ref&amp;gt;&amp;lt;ref name=CUDA&amp;gt;Araújo, G.F., H.T. Macedo, M.T. Chella, C.A.E. Montesco and M.V.O. Medeiros. PARALLEL IMPLEMENTATION OF EXPECTATION-MAXIMISATION ALGORITHM FOR THE TRAINING OF GAUSSIAN MIXTURE MODELS [https://ri.ufs.br/bitstream/123456789/1764/1/ExpectationMaximisationAlgorithm.pdf]&amp;lt;/ref&amp;gt;, в которых представлены параллельные реализации EM алгоритма, описывают помимо использующихся программных и аппаратных решений результаты проведенных экспериментов с данными. В качестве примера в этом разделе будут рассмотрены результаты эксперементов, проведенных со связующим программным обеспечением (&#039;&#039;middleware&#039;&#039;) FREERIDE&amp;lt;ref&amp;gt;Leonid Glimchera, Ruoming Jinb, Gagan Agrawala. Middleware for data mining applications on clusters and grids [http://www.cs.kent.edu/~jin/Papers/JPDC08.pdf]&amp;lt;/ref&amp;gt; (FRamework for Rapid Implementation of Datamining Engines), обеспечивающим возможность распараллеливания как для систем с общей памятью (в частности, симметричных мультипроцессорных систем), так и для систем с распределенной памятью.&lt;br /&gt;
&lt;br /&gt;
Эксперименты проводились на кластере машин Pentium 700MHz связанных при помощи Myrinet&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Myrinet&amp;lt;/ref&amp;gt; LANai 7.0 на трех наборах данных: &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;а)&#039;&#039;&#039; 3.3 * 10^6 объектов&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;b)&#039;&#039;&#039; 6.2 * 10^6 объектов&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;c)&#039;&#039;&#039; 12.5 * 10^6 объектов&lt;br /&gt;
&lt;br /&gt;
Объекты представляют собой координаты точек 10-мерного пространства.&lt;br /&gt;
 &lt;br /&gt;
Количество машин в кластере варьировалось от 1 до 8, при этом на каждой машине запускалось до четырех параллельных потоков.&lt;br /&gt;
&lt;br /&gt;
Результаты экспериментов представлены на рисунках 7-9&amp;lt;ref name=FREERIDE/&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
{|align=&amp;quot;center&amp;quot;&lt;br /&gt;
 |-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
 |[[file:EM_FREERIDE_experiments_a.png|thumb|center|350px|Рисунок 7: набор данных a)]]&lt;br /&gt;
 |[[file:EM_FREERIDE_experiments_b.png|thumb|center|357px|Рисунок 8: набор данных b)]]&lt;br /&gt;
 |[[file:EM_FREERIDE_experiments_c.png|thumb|center|351px|Рисунок 9: набор данных c)]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что используемые в данном исследовании машины, как и коммуникационная среда, сейчас не используются и считаются устаревшими, результат приведенных экспериментов наглядно показывает, что EM алгоритм хорошо параллелится, зависимость ускорения от числа узлов в кластере с небольшим количеством узлов близка к линейной, а также, что скорость работы алгоритма линейно зависит от числа объектов.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&#039;&#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;
Примеры библиотек, содержащих последовательную реализацию EM-алгоритма, или отдельных реализаций:&lt;br /&gt;
&lt;br /&gt;
# [http://docs.opencv.org/2.4/modules/ml/doc/expectation_maximization.html OpenCV(C++)] ([https://github.com/opencv/opencv/blob/master/modules/ml/src/em.cpp github])&lt;br /&gt;
# [http://www.mathworks.com/help/stats/clustering-using-gaussian-mixture-models.html Matlab]&lt;br /&gt;
# [http://scikit-learn.org/stable/modules/mixture.html Scikit learn (Python)]&lt;br /&gt;
# [http://mlpack.org/index.html MLPack(C++)]&lt;br /&gt;
&lt;br /&gt;
Примеры библиотек, содержащих параллельную реализацию EM-алгоритма, или отдельных реализаций:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Здесь приводятся как конкретные реализации, так и статьи, описывающие подходы к реализациям распараллеливания EM-алгоритма&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
# [https://spark.apache.org/ Apache Spark]&lt;br /&gt;
# [http://accord-framework.net/ Accord.NET Framework (C#)]&lt;br /&gt;
# Статья об использовании FREERIDE middleware для распараллеливания EM алгоритма &amp;lt;ref name=FREERIDE/&amp;gt; &lt;br /&gt;
# [http://andrewharp.com/gmmcuda реализация с использованием CUDA]&lt;br /&gt;
# [https://github.com/Corv/CUDA-GMM-MPI еще одна реализация с использованием CUDA]&lt;br /&gt;
# статья об использовании параллельного EM алгоритма в задачах компьютерного зрения &amp;lt;ref name=CV/&amp;gt;&lt;br /&gt;
# статья о распараллеливании EM алгоритма с использованием CUDA &amp;lt;ref name=CUDA/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Algoman</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%95%D0%BA%D0%B0%D1%82%D0%B5%D1%80%D0%B8%D0%BD%D0%B0%D0%9A%D0%BE%D0%B7%D1%8B%D1%80%D0%B5%D0%B2%D0%B0/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%B4%D0%B8%D0%BD%D0%B0%D0%BC%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B9_%D0%B8%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B9_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_CHAMELEON&amp;diff=18769</id>
		<title>Участник:ЕкатеринаКозырева/Алгоритм динамической иерархической кластеризации CHAMELEON</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%95%D0%BA%D0%B0%D1%82%D0%B5%D1%80%D0%B8%D0%BD%D0%B0%D0%9A%D0%BE%D0%B7%D1%8B%D1%80%D0%B5%D0%B2%D0%B0/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%B4%D0%B8%D0%BD%D0%B0%D0%BC%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B9_%D0%B8%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B9_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_CHAMELEON&amp;diff=18769"/>
		<updated>2016-11-21T11:27:19Z</updated>

		<summary type="html">&lt;p&gt;Algoman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Алгоритм динамической иерархической кластеризации CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(nm + n log n + m^2 log m)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;\frac{n (n - 1)}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n+ n log(n) + m^2 log (m) + m log(m))&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;
}}&lt;br /&gt;
&lt;br /&gt;
Автор описания [[Участник:ЕкатеринаКозырева|Е.А.Козырева]]&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Алгоритм CHAMELEON был предложен в 1999 году тремя учеными из университета Миннесоты – George Karypis, Eui-Hong (Sam) Han и Vipin Kumar&amp;lt;ref&amp;gt;George Karypis, Eui-Hong (Sam) Han и Vipin Kumar, «Chameleon: Hierarchical Clustering Using Dynamic Modeling», 1999.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Предназначен для решения задач кластеризации. Кластеризация (или кластерный анализ) — это задача разбиения множества объектов на группы, называемые кластерами. Внутри каждой группы должны оказаться «похожие» объекты, а объекты разных группы должны быть как можно более отличны.&lt;br /&gt;
&lt;br /&gt;
CHAMELEON - это агломеративный иерархический алгоритм кластеризации, ключевой особенностью которого является то, что он учитывает и взаимную связность, и сходство при определении наиболее похожей пары подкластеров, основываясь на динамической модели. Это означает, что в процессе кластеризации два кластера объединяются, только если их относительная взаимная связность и относительное взаимное сходство являются высокими по отношению к внутренней взаимосвязанности кластеров и близости элементов внутри кластеров. Кроме того, CHAMELEON использует подход для моделирования степени взаимосвязанности и близости между каждой парой кластеров, который учитывает внутренние характеристики самих кластеров. Таким образом, он может автоматически адаптироваться к внутренним характеристикам объединяемых кластеров.&lt;br /&gt;
&lt;br /&gt;
CHAMELEON находит кластеры в наборе данных с помощью трехфазного алгоритма. На первой фазе происходит построение графа, путём добавления рёбер по принципу k ближайших соседей. На второй фазе CHAMELEON группирует полученные элементы в множество относительно небольших подграфов. Во время третьей фазы применяется агломеративный иерархический алгоритм кластеризации, с помощью которого находятся естесственные кластеры путем многократного объединения подграфов, полученных на прошлом этапе.&lt;br /&gt;
&lt;br /&gt;
[[File:Chameleon.png|1000px|thumb|center|Рисунок 1. Общая структура алгоритма CHAMELEON]]&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Исходные данные&#039;&#039;: &lt;br /&gt;
&lt;br /&gt;
* Множество из n точек &amp;lt;math&amp;gt;V= {v_{ij}}&amp;lt;/math&amp;gt; в метрическом пространстве, которое задано симметрической матрицей расстояний &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;n\times n&amp;lt;/math&amp;gt;.&lt;br /&gt;
* &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество ближайших соседей для вершин, &amp;lt;math&amp;gt;k \in N, k \leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
* &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; - наименьшее число вершин, которое может содержать наибольший подграф на 2-м этапе, &amp;lt;math&amp;gt;l \in N, l \leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Обозначения&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; - граф, полученный путём соединения каждой точки с её &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайшими соседями.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;K= \{K_{i}\}&amp;lt;/math&amp;gt; - разбиение множества &amp;lt;math&amp;gt;V&amp;lt;/math&amp;gt; на набор попарно непересекающихся связных подмножеств, полученное в результате выполнения второй фазы алгоритма.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;G_{2} = (K, E_{2})&amp;lt;/math&amp;gt; - взвешенный граф, вершинами которого являются получившиеся подграфы, а ребрами - количество ребер исходного графа, соединяющих соответствующие подграфы.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;C = \{C_{i}\}&amp;lt;/math&amp;gt; - итоговое разбиение множества вершин графа &amp;lt;math&amp;gt;G_{2}&amp;lt;/math&amp;gt; на набор кластеров.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Вспомогательные понятия&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Определяется как сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. Внутренняя связность &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{|EC_{(C_{i},C_{j})}|}{(|EC_{C_{i}}|+|EC_{C_{j}}|)/2}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Подсчитывается как среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Определяется как абсолютное сходство между этой парой кластеров, нормализованное с учетом их внутреннего сходства&amp;lt;ref&amp;gt;http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый этап&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
На первом этапе, согласно графо-ориентированному подходу, происходит построение графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; на матрице сходства объектов по принципу k ближайших соседей. Две вершины такого графа соединяет ребро, если объект, соответствующий любой из этих вершин попадает в число k наиболее близких объектов для объекта, соответствующего другой вершине из данной пары.&lt;br /&gt;
[[Файл:Снимок chameleon 2.png|2000px|thumb|Рисунок 2. Объекты в пространстве - слева, граф по принципу 1-го ближайшего соседа - по центру, граф по принципу 3-х ближайших соседей - справа ]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй этап&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Алгоритм разделяет полученный граф на множество сравнительно малых подграфов &amp;lt;math&amp;gt;K= \{K_{i}\}&amp;lt;/math&amp;gt;. Разделение происходит последовательно. На каждом шаге выбирается подграф, содержащий наибольшее число вершин. Этот граф разделяется на два подграфа так, что разделитель ребер графа минимален и каждый из получаемых подграфов содержит не менее 25 % вершин исходного графа. Процесс разделения останавливается, когда наибольший подграф содержит меньше некоторого заданного числа вершин. Обычно величина этого параметра задается равной значению от 1 до 5 % от числа объектов. Полученное множество связных графов считается множеством начальных кластеров, на котором требуется провести последовательное иерархическое объединение.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Третий этап&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Третий этап заключается в итеративном преобразовании множества подграфов &amp;lt;math&amp;gt;K= \{K_{i}\}&amp;lt;/math&amp;gt; в множество кластеров &amp;lt;math&amp;gt;C = \{C_{i}\}&amp;lt;/math&amp;gt;. Алгоритм осуществляет агломеративную иерархическую кластеризацию на основании показателей &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Существует две стратегии анализа показателей сходства. Первая подразумевает наличие некоторых пороговых значений &amp;lt;math&amp;gt;T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;T_{RC}&amp;lt;/math&amp;gt;. В соответствии с этой стратегией, алгоритм для каждого кластера &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; проверяет, отвечают ли смежные (наиболее близкие) ему кластеры условиям:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} \geqslant T_{RI}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} \geqslant T_{RC}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если более одного смежного кластера отвечает этим условиям, то алгоритм выбирает для объединения наиболее связный кластер (граф), то есть такой кластер &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;, с которым у кластера &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; получается наибольшая абсолютная взаимная связность. По завершению прохода по всем кластерам, созданные таким образом пары объединяются. Параметры &amp;lt;math&amp;gt;T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;T_{RC}&amp;lt;/math&amp;gt; могут использоваться для изменения характеристик получаемых кластеров.&lt;br /&gt;
&lt;br /&gt;
Вторая стратегия заключается в использовании специальной функции, объединяющей понятия относительной взаимной связности и относительного взаимного сходства. На каждом шаге выбираются те кластеры для объединения, которые максимизируют эту функцию:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; выбирается пользователем. Если &amp;lt;math&amp;gt;\alpha &amp;gt; 1 &amp;lt;/math&amp;gt;, то алгоритм придает большее значение относительному взаимному сходству, а если &amp;lt;math&amp;gt;\alpha &amp;lt;  1 &amp;lt;/math&amp;gt;, то большее значение имеет относительная взаимная связность.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Вычисляемые данные&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;U = (u_1, u_2, ..., u_n)&amp;lt;/math&amp;gt; - n-мерный вектор, где &amp;lt;math&amp;gt;u_i \in N_{[C]}&amp;lt;/math&amp;gt; - порядковый номер кластера, к которому принадлежит вершина i исходного множества V.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм имеет три вычислительных ядра, по одному на каждый этап.&lt;br /&gt;
&lt;br /&gt;
На первом этапе вычислительным ядром является процесс нахождения &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей для каждой вершины, который заключается в анализе матрицы расстояний.&lt;br /&gt;
&lt;br /&gt;
На втором этапе вычислительным ядром является процесс поиска подходящего разбиения очередного подграфа на два графа с минимизацией разделителя ребер графа.&lt;br /&gt;
&lt;br /&gt;
На третьем этапе вычислительным ядром является расчет величин &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; для каждой пары смежных кластеров.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Как уже рассказывалось ранее, алгоритм включает в себя три основных этапа, каждый из которых, по сути, является отдельным алгоритмом. Этапы выполняются последовательно относительно друг друга. &lt;br /&gt;
&lt;br /&gt;
Макрооперация на первом этапе - процедура нахождения &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей, на втором - процедура разбиения наибольшего подграфа на два графа, на третьем - процедура вычисления показателей сходства, на основе которых принимается решение о слиянии подграфов в кластер.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый этап&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
 int n; //количество вершин&lt;br /&gt;
 int k; //количество соседей&lt;br /&gt;
 int A[n][n] //матрица расстояний&lt;br /&gt;
 int D[k] //массив вершин-соседей&lt;br /&gt;
 int E[n][n] //матрица ребер графа &amp;lt;math&amp;gt;G_{2} = (K, E_{2})&amp;lt;/math&amp;gt;&lt;br /&gt;
 for i=1 to n-1 do&lt;br /&gt;
     {&lt;br /&gt;
       for j=i+1 to n do &lt;br /&gt;
            {&lt;br /&gt;
               //заполняем массив вершин-соседей вставляя новые вершины, если они ближе, чем самая далекая из массива. &lt;br /&gt;
            }&lt;br /&gt;
       for j=0 to k do &lt;br /&gt;
            {&lt;br /&gt;
               //для каждой вершины соседа заполняем соответствующую ячейку из матрицы E[n][n] единицей&lt;br /&gt;
            }&lt;br /&gt;
   &lt;br /&gt;
     }&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй этап&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 1. Все связные подграфы в отсортированном порядке помещаются в список;&lt;br /&gt;
 2. Берем наибольший элемент списка, вычисляем количество его вершин. Если число вершин &amp;gt; l, то идем в пункт 3. Иначе в пункт 5;&lt;br /&gt;
 3. Разбиваем подграф на два подграфа таким образом, чтобы разделитель ребер графа был минимален и каждый из получаемых подграфов содержал не менее 25 % вершин исходного графа;&lt;br /&gt;
 4. Добавляем полученные элементы в список подграфов таким образом, чтобы список оставался отсортированным. Идем в пункт 2;&lt;br /&gt;
 5. Нашли искомое множество подграфов math&amp;gt;K = \{K_{i}\}&amp;lt;/math&amp;gt;;&lt;br /&gt;
 6. Создаем и заполняем матрицу матрицу расстояний для графа &amp;lt;math&amp;gt;G_{2} = (K, E_{2})&amp;lt;/math&amp;gt;. Получаем искомый набор рёбер &amp;lt;math&amp;gt;E_{2}&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;
 1. Заводим два массива: а) массив кластеров C, полученных на предыдущем этапе, б) массив объединений кластеров F, которые мы будем получать на этом этапе;&lt;br /&gt;
 2. Берем следующий кластер &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; (на первом шаге - первый). Если все кластеры просмотрены, идем в пункт 6;&lt;br /&gt;
 3. Берем следующий кластер &amp;lt;math&amp;gt;C_{j}, i&amp;lt;&amp;gt;j&amp;lt;/math&amp;gt;. Если все кластеры просмотрены, то идем в пункт 2;&lt;br /&gt;
 4. Проверяем смежность &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;. Если не смежны, то возвращаемся в пункт 3. Если смежны, идем в пункт 5;&lt;br /&gt;
 5. Рассчитываем показатели &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Проверяем, удовлетворяют ли найденные значения условиям:&lt;br /&gt;
 *&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} \geqslant T_{RI}&amp;lt;/math&amp;gt;&lt;br /&gt;
 *&amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} \geqslant T_{RC}&amp;lt;/math&amp;gt;&lt;br /&gt;
 Если нет, то идем в пункт 3. Иначе если смежность пары кластеров выше, чем у предыдущих найденных, то &amp;lt;math&amp;gt;F_{i}=j&amp;lt;/math&amp;gt;. Идем в пункт 3;&lt;br /&gt;
 6. Если в списке F есть хотя бы одна пара кластеров для слияния, то выполняем слияние, обновляем массив кластеров и массив объединений кластеров. Идем в пункт 2.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
1) Для построения графа на основе метода k ближайших соседей для n вершин требуется &amp;lt;math&amp;gt;O(n log(n))&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;J.H. Friedman, J.L. Bentley, and R.A. Finkel. An algorithm for ﬁnding best matches in logarithmic expected time. ACM Transactions on Mathematical Software, 3:209–226, 1977.&amp;lt;/ref&amp;gt;; для наборов данных большой размерности эта величина составляет &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;S. Berchtold, C. Bohm, D. Keim, and H.-P. Kriegel. Cost model for nearest neighbor search in high dimensional data space. In Proc. of Symposium on Principles of Database Systems, Tucson, Arizona, 1997.&amp;lt;/ref&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
2) Для выделения множества сравнительно малых связных подграфов требуется &amp;lt;math&amp;gt;nm&amp;lt;/math&amp;gt; операций, где &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - количество подграфов, полученных на втором этапе алгоритма;&lt;br /&gt;
&lt;br /&gt;
3) Формирование набора кластеров, на основе множества подграфов, полученных на предыдущем этапе, требует &amp;lt;math&amp;gt;m^2log(m)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Итого, для n вершин получаем последовательную сложность &amp;lt;math&amp;gt;O(n log(n)+nm+m^2log(m))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
[[File:СК.png]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Первый этап работы алгоритма можно распределить между &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; процессами. На вход каждому процессу подается своя вершина, далее происходит процедура поиска &amp;lt;math&amp;gt;k&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;
&lt;br /&gt;
Второй этап распараллеливается путем подачи на вход свободному процессу очередного подграфа для разделения. Число итераций оценивается в &amp;lt;math&amp;gt;O(n log(n))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Третий этап делится на расчет показателей схожести и соединение подграфов в кластеры. Процесс расчета показателей можно распараллелить, подавая каждому процессу на вход пару подграфов. Сложность этого процесса оценивается как &amp;lt;math&amp;gt;m log(m)&amp;lt;/math&amp;gt;. Соединение подграфов в кластеры выполняется последовательно, сложность процесса составляет &amp;lt;math&amp;gt;m^2 log(m)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Таким образом получаем общую параллельную сложность алгоритма: &amp;lt;math&amp;gt;O(n+ n log(n) + m^2 log (m) + m log(m))&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;
1. Симметрическая матрица &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; расстояний между элементами данных размера &amp;lt;math&amp;gt;n\times n&amp;lt;/math&amp;gt; с нулями на главной диагонали  (&amp;lt;math&amp;gt;a_{ii}= 0, i = 1, \ldots, N&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
2. &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество ближайших соседей для вершин (рекомендуемое значение &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; от 5 до 20 в зависимости от количества анализируемых объектов).&lt;br /&gt;
&lt;br /&gt;
3. &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; - наименьшее число вершин, которое может содержать наибольший подкластер на 2-м этапе . Величина этого параметра варьируется от 1 до 5 % от общего числа объектов.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\frac{n (n - 1)}{2}&amp;lt;/math&amp;gt; (в силу симметричности и нулевой главной диагонали достаточно хранить только  над/поддиагональные элементы).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Вектор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; чисел &amp;lt;math&amp;gt;u_{1}, u_{2}, \ldots, u_{N}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;u_{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;Объём выходных данных&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&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; для больших наборов данных и логарифмическим для n вершин. На втором этапе сложно оценить это соотношение - оно сильно зависит от параметров &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt;. На третьем этапе соотношение равно &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Оценка &#039;&#039;вычислительной мощности&#039;&#039; выглядит следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;                  для 1-го этапа;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O(\frac{nm}{n^2+m^2})&amp;lt;/math&amp;gt;   для 2-го этапа;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O(\frac{m^2log(m)}{m^2+n})&amp;lt;/math&amp;gt; для 3-го этапа;&lt;br /&gt;
&lt;br /&gt;
Алгоритм является &#039;&#039;недетерминированным&#039;&#039;. Хотя 1-й этап детерминирован, на 2-ом этапе могут быть найдены различные разбиения на подграфы, что повлияет и на итоговый результат работы алгоритма.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
Масштабируемость исследовалась на основе работы, презентующей пробную версию параллельной реализации алгоритма для различного числа потоков&amp;lt;ref&amp;gt;http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf&amp;lt;/ref&amp;gt;.&lt;br /&gt;
График показывает, что эффективность и скорость работы алгоритма растут с увеличением объема входных данных. Однако, в упомянутой выше работе отмечается, что эффективность алгоритма падает с ростом количества потоков.&lt;br /&gt;
&lt;br /&gt;
[[File:Масштабирование.png|700px|center]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Последовательная реализация алгоритма доступна по ссылке &amp;lt;ref&amp;gt;http://read.pudn.com/downloads36/sourcecode/math/115779/chameleon/chameleon.c__.htm&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
CHAMELEON можно реализовать с использованием графовых библиотек METIS &amp;lt;ref&amp;gt;http://glaros.dtc.umn.edu/gkhome/metis/metis/overview&lt;br /&gt;
&amp;lt;/ref&amp;gt;, hMETIS &amp;lt;ref&amp;gt;http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview&amp;lt;/ref&amp;gt; и RANN &amp;lt;ref&amp;gt;https://cran.r-project.org/web/packages/RANN/index.html&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, оно было рассмотрено в пункте 2.4.&lt;br /&gt;
&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON не найдено.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Algoman</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%95%D0%BA%D0%B0%D1%82%D0%B5%D1%80%D0%B8%D0%BD%D0%B0%D0%9A%D0%BE%D0%B7%D1%8B%D1%80%D0%B5%D0%B2%D0%B0&amp;diff=18768</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%95%D0%BA%D0%B0%D1%82%D0%B5%D1%80%D0%B8%D0%BD%D0%B0%D0%9A%D0%BE%D0%B7%D1%8B%D1%80%D0%B5%D0%B2%D0%B0&amp;diff=18768"/>
		<updated>2016-11-21T11:27:05Z</updated>

		<summary type="html">&lt;p&gt;Algoman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Замечания к [[Участник:ЕкатеринаКозырева/Алгоритм_динамической_иерархической_кластеризации_CHAMELEON]] ==&lt;br /&gt;
&lt;br /&gt;
1) отсутствует оценка высоты и ширины ЯПФ параллельного алгоритма во врезке в начале статьи&lt;br /&gt;
&lt;br /&gt;
2) требуется какая-то подпись или ссылка на рисунок в п 1.1&lt;br /&gt;
&lt;br /&gt;
3) подпись к рисунку 1.2 должны быть выполнена средствами разметки, а не на самой картинке&lt;br /&gt;
&lt;br /&gt;
4) для оформления (псевдо) кода следует использовать тег &amp;lt;nowiki&amp;gt;&amp;lt;source lang=&amp;quot;...&amp;quot;&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5) отсутствует оценка вычислительной мощности алгоритма в п 1.10 &lt;br /&gt;
&lt;br /&gt;
6) пункты 2.1 и 2.2 должны быть 2.4 и 2.7, согласно формату описания [[Структура_описания_свойств_алгоритмов]]&lt;br /&gt;
&lt;br /&gt;
7) список литературы оформлен неправильно - см. как сделано в [[Разложение_Холецкого_(метод_квадратного_корня)]]&lt;br /&gt;
&lt;br /&gt;
== Замечания к пункту 2.4 от 16.11.2016 == &lt;br /&gt;
&lt;br /&gt;
* отсутствует пункт 2.4&lt;br /&gt;
&lt;br /&gt;
== Замечания к пункту 2.4 от 21.11.2016 == &lt;br /&gt;
&lt;br /&gt;
* для выполнения задания практикума иследование масштабируемости должно быть проведено самостоятельно&lt;/div&gt;</summary>
		<author><name>Algoman</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:Ruslanlazovskiy/CHAMELEON&amp;diff=18764</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</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:Ruslanlazovskiy/CHAMELEON&amp;diff=18764"/>
		<updated>2016-11-21T11:21:13Z</updated>

		<summary type="html">&lt;p&gt;Algoman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Algoman}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n^2 / 2&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] ( разделы 1.1 - 1.4 , 1.7 , 1.8 ),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87|&amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] ( разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2 )&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики ( простейший пример - евклидова метрика ). Не следует путать задачу кластеризации с задачей классификации - в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения. Первоначально алгоритм был описан в статье&amp;lt;ref&amp;gt;CHAMELEON: A Hierarchical Clustering Algorithm Using Dynamic Modeling. George Karypis, Eui-Hong Han, Vipin Kumar. IEEE Computer 32(8): 68-75, 1999&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик ( возможные метрики будут подробно описаны далее ). Число получаемых в итоге кластеров в явном виде не задаётся.&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt; ( возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой. К исходным данным также относится набор параметров. Это &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество ближайших соседей на первом этапе алгоритма, &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - отношение количества вершин в наибольшем подграфе по отношению к общему числу объектов на втором этапе алгоритма, а также параметры &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - пороговые значения, после которых прекращается агломеративная кластеризация на третьем этапе. Следует особо отметить, что число получаемых в итоге кластеров заранее не известно, хотя на него и можно повлиять изменением значений перечисленных параметров.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей, где &amp;lt;math&amp;gt;V&amp;lt;/math&amp;gt; - множество вершин графа ( т.е. объекты ), а &amp;lt;math&amp;gt;E&amp;lt;/math&amp;gt; - множество ребер графа ( т.е. построенные связи между ближайшими соседями ). Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. Параметр &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; явно не задаётся, выполнение этого этапа алгоритма прекращается по выполнении описанных далее условий. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии анализа показателей сходства. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&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;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(nm + nlog{n} + mlog{m})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число исходных объектов, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - число малых кластеров, полученных после первого этапа работы. В случае &amp;quot;предельного&amp;quot; разбиения &amp;lt;math&amp;gt;m = n&amp;lt;/math&amp;gt; эта оценка превращается в &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;. В любом случае эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов (авторы оригинальной статьи в своих исследованиях подразумевают, что матрица смежности уже построена), что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Тогда оценка будет составлять &amp;lt;math&amp;gt;O(n^2 + nm + nlog{n} + mlog{m})&amp;lt;/math&amp;gt; операций или &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; в случае &amp;quot;предельного&amp;quot; разбиения.&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений ( для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON ( см. раздел &amp;quot;Существующие реализации&amp;quot; ). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;q - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами, где q - количество кластеров на этой итерации.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа в этих терминах - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации ( такая кластеризация, очевидно, не будет иметь практического смысла ), в то время как 2-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
===Локальность данных и вычислений===&lt;br /&gt;
===Возможные способы и особенности параллельной реализации алгоритма===&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Как можно увидеть из раздела &amp;quot;существующие реализации&amp;quot;, параллельной реализации алгоритма CHAMELEON на система с распределенной памятью найдено не было. Однако в &amp;lt;ref name = &amp;quot;exp&amp;quot;&amp;gt;Parallel Algorithm for the Chameleon Clustering Algorithm using Dynamic Modeling.  Rajnish Dashora, Harsh Bajaj, Akshat Dube, Geetha Mary .A. VIT University,Vellore. International Journal of Computer Applications (0975 – 8887) Volume 79 – No8, October 2013 &amp;lt;/ref&amp;gt;. приводится экспериментальный вариант параллельной реализации посредством OpenMP для систем с общей памятью, включающий в себя значительную модификацию исходного алгоритма, но не приводится рабочая реализация.&lt;br /&gt;
&lt;br /&gt;
В силу вышескасновного основное внимание будет уделено исследованию масштабируемости алгоритма по размеру задачи, в пределах одного узла. Далее приводятся графики производительности в Гфлопс для различных размеров задачи. Эффективность работы алгоритма убывает на всей рассматриваемой области. Темпы убывания эффективности снижаются с ростом размера задачи.&lt;br /&gt;
&lt;br /&gt;
Для исследования такой масштабируемости вширь использовалась референсная последовательная реализация алгоритма ( м. раздел &amp;quot;Существующие реализации&amp;quot; ). Соответствующая программа запускалась на системе BG/P на одном вычислительном узле. Характеристики вычислительного узла, а также микропроцессорного ядра - элемента такого узла, приводятся в &amp;lt;ref&amp;gt;http://hpc.cmc.msu.ru/bgp&amp;lt;/ref&amp;gt; Таким образом, удостоверенными экспериментальными данными являются только значения, полученные для случая 1 процесса. Значения для случаев 2 и 4 процессов являются ОЦЕНОЧНЫМИ и выводятся из результатов работы модифицированной версии алгоритма, исследуемой в &amp;lt;ref name = &amp;quot;exp&amp;quot;&amp;gt;Parallel Algorithm for the Chameleon Clustering Algorithm using Dynamic Modeling.  Rajnish Dashora, Harsh Bajaj, Akshat Dube, Geetha Mary .A. VIT University,Vellore. International Journal of Computer Applications (0975 – 8887) Volume 79 – No8, October 2013 &amp;lt;/ref&amp;gt;. К сожалению, указанной реализации авторы не предоставляют. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON performance.png|800px]]&lt;br /&gt;
&lt;br /&gt;
===Динамические характеристики и эффективность реализации алгоритма===&lt;br /&gt;
===Выводы для классов архитектур===&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
С копией референсной реализации иерархической кластеризации, взятой с данного ресурса [http://us.codeforge.com/article/192925 Sequental], в случае неработоспособности последнего, можно ознакомиться здесь [http://pastebin.com/PhC4X0Cy Copy]&amp;lt;br/&amp;gt;&lt;br /&gt;
Последовательная реализация алгоритма CHAMELEON использовалась в статье &amp;lt;ref&amp;gt;Clustering Of Web Usage Data Using&lt;br /&gt;
Chameleon Algorithm, T.Vijaya Kumar, Dr. H.S.Guruprasad, International Journal of Innovative Research in Computer&lt;br /&gt;
and Communication Engineering, Vol. 2, Issue 6, June 2014&amp;lt;/ref&amp;gt;&lt;br /&gt;
Теоретически возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, например [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview METIS ], [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview hMETIS] и [https://cran.r-project.org/web/packages/RANN/index.html RANN].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf параллельная реализация].&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Краткий обзор алгоритма [http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Первоначальная статья от авторов алгоритма [http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Исследования возможной параллелизации алгоритма[http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|]&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Algoman</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%90%D1%80%D1%82%D0%B5%D0%BC_%D0%A2%D0%B0%D1%80%D0%B0%D0%BD/%D0%93%D1%80%D0%B0%D1%84%D0%BE-%D0%BE%D1%80%D0%B8%D0%B5%D0%BD%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_CHAMELEON&amp;diff=18056</id>
		<title>Участник:Артем Таран/Графо-ориентированный алгоритм кластеризации CHAMELEON</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%90%D1%80%D1%82%D0%B5%D0%BC_%D0%A2%D0%B0%D1%80%D0%B0%D0%BD/%D0%93%D1%80%D0%B0%D1%84%D0%BE-%D0%BE%D1%80%D0%B8%D0%B5%D0%BD%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_CHAMELEON&amp;diff=18056"/>
		<updated>2016-11-18T09:07:42Z</updated>

		<summary type="html">&lt;p&gt;Algoman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Algoman}}&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Графо-ориентированный алгоритм кластеризации CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n^2+nm+m^2log(m))&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n + log(n) + mlog(m) + m^2log(m))&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;\frac{n (n - 1)}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Статью подготовили: [[Участник:Артем_Таран|Артём Таран Иванович]] (разделы 1.1 - 1.10, 2.7), [[Участник:ShimchikN|Шимчик Никита Владимирович]] (разделы 1.1 - 1.10, 2.7).&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Кластеризация — многомерная статистическая процедура, выполняющая сбор данных, содержащих информацию о выборке объектов, и затем упорядочивающая объекты в сравнительно однородные группы (кластеры) с минимизацией межкластерного сходства и максимизацией внутрикластерного сходства.&lt;br /&gt;
&lt;br /&gt;
Графо-ориентированный алгоритм кластеризации CHAMELEON&amp;lt;ref name=&amp;quot;rt&amp;quot;&amp;gt;http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf&amp;lt;/ref&amp;gt; - алгоритм, который измеряет сходство двух кластеров на основе&lt;br /&gt;
динамической модели. В процессе кластеризации два кластера объединяются, только если показатели взаимосвязанности и близости между двумя кластерами являются высокими по отношению к показателям внутренней взаимосвязанности кластеров и близости элементов внутри этих кластеров. Процесс слияния с использованием динамической модели, использующийся в данном алгоритме облегчает открытие&lt;br /&gt;
природных и однородных кластеров. Методология динамического моделирования кластеров, использующаяся в CHAMELEON,&lt;br /&gt;
применима ко всем типам данных, для которых может быть построена матрица подобия.&lt;br /&gt;
&lt;br /&gt;
Следует отметить, что конечное число кластеров не задаётся явным образом и зависит как от выбора параметров алгоритма, так и от внутренней структуры входных данных.&lt;br /&gt;
&lt;br /&gt;
Алгоритм кластеризации CHAMELEON включает в себя три этапа:&lt;br /&gt;
&lt;br /&gt;
1) Построение графа, путём добавления рёбер по принципу k ближайших соседей.&lt;br /&gt;
&lt;br /&gt;
2) Выделение множества сравнительно малых связных подграфов.&lt;br /&gt;
&lt;br /&gt;
3) Формирование набора кластеров, на основе множества подграфов, полученных на предыдущем этапе.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Графы k ближайших соседей.jpg|1000px|thumb|center|Графы k ближайших соседей: 1) объекты в пространстве, 2) граф по принципу 1-го ближайшего соседа, 3) граф по принципу 2-го ближайшего соседа, 4) граф по принципу 3-х ближайших соседей&amp;lt;ref name=&amp;quot;rt&amp;quot;&amp;gt;http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf&amp;lt;/ref&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
==== Данные ====&lt;br /&gt;
* &#039;&#039;&#039;Исходные данные&#039;&#039;&#039;: множество из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; точек &amp;lt;math&amp;gt;V = \{v_{i}\}&amp;lt;/math&amp;gt; в метрическом пространстве, которое может быть задано в виде треугольной матрицы расстояний &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;n\times n&amp;lt;/math&amp;gt;; натуральное число &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;, используемое в качестве параметра алгоритма поиска k ближайших соседей.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Промежуточный результат после первого этапа&#039;&#039;&#039;: граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, полученный путём соединения каждой точки с её &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайшими соседями.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Промежуточный результат после второго этапа&#039;&#039;&#039;: разбиение множества &amp;lt;math&amp;gt;V&amp;lt;/math&amp;gt; на набор &amp;lt;math&amp;gt;K = \{K_{i}\}&amp;lt;/math&amp;gt; попарно непересекающихся связных подмножеств, из которого образуется взвешенный граф &amp;lt;math&amp;gt;G_{2} = (K, E_{2})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Промежуточный результат после третьего этапа&#039;&#039;&#039;: итоговое разбиение множества вершин графа &amp;lt;math&amp;gt;G_{2}&amp;lt;/math&amp;gt; на набор кластеров &amp;lt;math&amp;gt;C = \{C_{i}\}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Вычисляемые данные&#039;&#039;&#039;: n-мерный вектор &amp;lt;math&amp;gt;v&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt;), показывающий отображение исходного множества точек на набор кластеров &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Определения ====&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Абсолютная взаимная связность между парой кластеров &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;&#039;&#039; определяется как сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; с вершинами из &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;. Эти ребра, фактически, входят в разделитель ребер графа, состоящего из кластеров &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;, и разбивающим его на подграфы &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;. Обозначается эта величина как&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Внутреннюю связность &amp;lt;math&amp;gt;EC_{C_{i}}&amp;lt;/math&amp;gt; кластера &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; можно вычислить как сумму ребер, входящих в разделитель ребер, разбивающий &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; на два совершенно равных подграфа.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Относительная взаимная &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; связность  пары кластеров &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;&#039;&#039; определяется формулой:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Учитывая значения относительной взаимной связности, можно добиться получения кластеров разного размера, формы и плотности, то есть общего внутреннего сходства.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Абсолютное взаимное сходство между парой кластеров &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;&#039;&#039; подсчитывается как среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; соответственно. Эти соединения обусловлены предыдущим разбиением общего графа, полученного на матрице сходства.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Относительное взаимное сходство &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; между парой кластеров &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;&#039;&#039; определяется как абсолютное сходство между этой парой кластеров, нормализованное с учетом их внутреннего сходства и вычисляется по формуле:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;S_{EC_{(C_{i})}}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;S_{EC_{(C_{i})}}&amp;lt;/math&amp;gt; - средние веса ребер (значения сходства), принадлежащих разделителю ребер кластеров &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; соответственно,&lt;br /&gt;
и &amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - средний вес ребер, соединяющих вершины &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; с вершинами &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;, причем ребра принадлежат разделителю ребер &amp;lt;math&amp;gt;EC_{(C_{i})}&amp;lt;/math&amp;gt;, определенному ранее.&lt;br /&gt;
&lt;br /&gt;
Далее, алгоритм применяет агломеративную иерархическую кластеризацию с использованием вышеозначенных показателей. Причем существует две стратегии их учета. Первая подразумевает наличие некоторых пороговых значений &amp;lt;math&amp;gt;T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;T_{RC}&amp;lt;/math&amp;gt;. В соответствии с этой стратегией, алгоритм для каждого кластера &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; проверяет, отвечают ли смежные (наиболее близкие) ему кластеры условиям:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} \geqslant T_{RI}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} \geqslant T_{RC}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если более одного смежного кластера отвечает этим условиям, то алгоритм выбирает для объединения наиболее связный кластер (граф), то есть такой кластер &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;, с которым у кластера &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; получается наибольшая абсолютная взаимная связность. По завершению прохода по всем кластерам, созданные таким образом пары объединяются. Параметры &amp;lt;math&amp;gt;T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;T_{RC}&amp;lt;/math&amp;gt; могут использоваться для изменения характеристик получаемых кластеров.&lt;br /&gt;
&lt;br /&gt;
Вторая стратегия заключается в использовании специальной функции, объединяющей понятия относительной взаимной связности и относительного взаимного сходства. На каждом шаге выбираются те кластеры для объединения, которые максимизируют эту функцию:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; выбирается пользователем. Если &amp;lt;math&amp;gt;\alpha &amp;gt; 1 &amp;lt;/math&amp;gt;, то алгоритм придает большее значение относительному взаимному сходству, а если &amp;lt;math&amp;gt;\alpha &amp;lt;  1 &amp;lt;/math&amp;gt;, то большее значение имеет относительная взаимная связность. Разумеется, данный подход позволяет получить полную дендрограмму кластерного анализа&amp;lt;ref name=&amp;quot;rty&amp;quot;&amp;gt;http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
&lt;br /&gt;
На первом этапе работы алгоритма вычислительным ядром можно считать процесс нахождения k ближайших соседей для каждой отдельной вершины.&lt;br /&gt;
&lt;br /&gt;
На втором этапе работы алгоритма вычислительным ядром является поиск разбиения графа на два подграфа с минимизацией разделителя рёбер графа.&lt;br /&gt;
&lt;br /&gt;
На третьем этапе работы алгоритма вычислительным ядром является расчёт &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; для пары смежных кластеров, а также их слияние.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап соответствует отдельному алгоритму. &lt;br /&gt;
&lt;br /&gt;
* Макрооперацией на первом этапе является процедура выделения k ближайших соседей.&lt;br /&gt;
&lt;br /&gt;
* Макрооперацией на втором этапе является процедура разбиения наибольшего подграфа на каждой итерации.&lt;br /&gt;
&lt;br /&gt;
* Макрооперациями на третьем этапе являются процедуры вычисления метрики для принятия решения об объединении кластеров и объединение кластеров на каждой итерации.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
* Первый этап (псевдокод):&lt;br /&gt;
  integer n; // Количество точек.&lt;br /&gt;
  integer k; // Параметр k&lt;br /&gt;
  integer A[n][n]; // Верхняя треугольная матрица расстояний между точками.&lt;br /&gt;
  &lt;br /&gt;
  integer E[n][n]; // Верхняя треугольная матрица рёбер графа G - изначально инициализирована нулями.&lt;br /&gt;
  foreach (integer i in (1,n-1) ) {&lt;br /&gt;
    integer Neighbours[k]; // матрица, используемая хранения ближайших соседей&lt;br /&gt;
    integer countN = 0;&lt;br /&gt;
    &lt;br /&gt;
    foreach (integer j in (i+1, n) ) {&lt;br /&gt;
      // Заполняем матрицу Neighbours, добавляя новые элементы и увеличивая счётчик countN.&lt;br /&gt;
      // Когда countN станет равен k, новые элементы будут вставляться на место старых, либо отбрасываться.&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    foreach (integer j in (0, countN) ) {&lt;br /&gt;
      E[min(i,j), max(i,j)] = 1;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  return E;&lt;br /&gt;
&lt;br /&gt;
* Второй этап:&lt;br /&gt;
  [[File:Диаграмма_шаг_2.png]]&lt;br /&gt;
&lt;br /&gt;
* Третий этап:&lt;br /&gt;
  [[File:Chameleon_stage_3.png|611px]]&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
1) Построение графа на основе метода k ближайших соседей в худшем случае требует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций;&lt;br /&gt;
&lt;br /&gt;
2) Для выделения множества сравнительно малых связных подграфов требуется &amp;lt;math&amp;gt;nm&amp;lt;/math&amp;gt; операций;&lt;br /&gt;
&lt;br /&gt;
3) Формирование набора кластеров, на основе множества подграфов, полученных на предыдущем этапе, требует &amp;lt;math&amp;gt;m^2log(m)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Итого, получаем последовательную сложность &amp;lt;math&amp;gt;O(n^2+nm+m^2log(m))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
&lt;br /&gt;
  [[File:Chameleon_inforgraph.png|811px]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Первый этап работы алгоритма можно распределить между &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; процессами: в этом случае каждому процессу назначается своя точка и происходит поиск &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей. Таким образом, его параллельная сложность составляет &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
На втором этапе количество задействованных процессов может варьироваться в зависимости от входных данных. В худшем случае число итераций можно оценить как &amp;lt;math&amp;gt;O(log(n))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
На третьем этапе можно распараллелить процесс расчёта метрик сходства между кластерами, однако итоговое слияние всё равно должно выполняться последовательно.&lt;br /&gt;
Поскольку процесс сравнения кластеров возможно распараллелить, сложность 3-го этапа составляет &amp;lt;math&amp;gt;mlog(m) + m^2log(m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Таким образом, суммарная параллельная сложность оказывается равна &amp;lt;math&amp;gt;O(n + log(n) + mlog(m) + m^2log(m))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
* Входные данные: &lt;br /&gt;
&lt;br /&gt;
1) Треугольная матрица &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;n\times n&amp;lt;/math&amp;gt; (где n — количество объектов), в которой элементу &amp;lt;math&amp;gt;a_{ij}&amp;lt;/math&amp;gt; соответствует расстояние между i-м и j-м объектами.&lt;br /&gt;
&lt;br /&gt;
2) Количество ближайших соседей &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; для вершин (рекомендуемое значение &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; от 5 до 20 в зависимости от количества анализируемых объектов).&lt;br /&gt;
&lt;br /&gt;
3) Наименьшее число вершин, которое может содержать наибольший подграф на 2-м этапе &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt;. Величина этого параметра варьируется от 1 до 5 % от общего числа объектов.&lt;br /&gt;
&lt;br /&gt;
* Объём входных данных: &amp;lt;math&amp;gt;\frac{n (n - 1)}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Выходные данные: n-мерный вектор &amp;lt;math&amp;gt;v&amp;lt;/math&amp;gt;, в котором элементу &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; соответствует номер кластера, присвоенный i-му объекту&lt;br /&gt;
&lt;br /&gt;
* Объём выходных данных: &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Первый этап алгоритма обладает хорошим ресурсом параллелизма: параллельная сложность его выполнения составляет &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;, что намного лучше последовательной оценки &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
У второго и третьего этапов алгоритма сложно полностью оценить ресурсы параллелизма. Но оба этапа возможно частично распараллелить.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вычислительную мощность&#039;&#039;&#039; для разных этапов алгоритма можно оценить как:&lt;br /&gt;
&lt;br /&gt;
1 этап: &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2 этап: &amp;lt;math&amp;gt;O(\frac{nm}{n^2+m^2})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3 этап: &amp;lt;math&amp;gt;O(\frac{m^2log(m)}{m^2+n})&amp;lt;/math&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью данного алгоритма является его недетерминированность. Несмотря на то, что 1-й этап детерминирован, алгоритм в целом является недетерминированным, так как на 2-ом этапе могут быть найдены различные разбиения на подграфы, а это повлияет и на итоговый результат работы алгоритма.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
&lt;br /&gt;
Проводилось исследование масштабируемости экспериментальной версии параллельной реализации алгоритма для малого числа потоков&amp;lt;ref name=&amp;quot;tr&amp;quot;&amp;gt;http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Его результаты отражены на графиках. Из графиков видно, что ускорение и эффективность алгоритма растут с увеличением объема данных.&lt;br /&gt;
&lt;br /&gt;
Однако можно заметить, что с увеличением числа потоков эффективность алгоритма падает.&lt;br /&gt;
&lt;br /&gt;
  [[File:Plot cham.jpg|850px|center]]&lt;br /&gt;
 &lt;br /&gt;
 [[File:Cham_speedup.png]] [[File:Cham_eff.png]]&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Существует несколько последовательных реализаций алгоритма. С одной из них можно ознакомиться по ссылке &amp;lt;ref name=&amp;quot;tra&amp;quot;&amp;gt;http://www.codeforge.com/article/192925&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, как, например METIS &amp;lt;ref name=&amp;quot;tru&amp;quot;&amp;gt;http://glaros.dtc.umn.edu/gkhome/metis/metis/overview&amp;lt;/ref&amp;gt; , hMETIS &amp;lt;ref name=&amp;quot;tri&amp;quot;&amp;gt;http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview&amp;lt;/ref&amp;gt; и RANN &amp;lt;ref name=&amp;quot;tro&amp;quot;&amp;gt;https://cran.r-project.org/web/packages/RANN/index.html&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь &amp;lt;ref name=&amp;quot;tr&amp;quot;&amp;gt;http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;/div&gt;</summary>
		<author><name>Algoman</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:EasyBreezy/%D0%A1%D1%82%D0%B0%D0%B1%D0%B8%D0%BB%D0%B8%D0%B7%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9_%D0%BC%D0%B5%D1%82%D0%BE%D0%B4_%D0%B1%D0%B8%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B3%D1%80%D0%B0%D0%B4%D0%B8%D0%B5%D0%BD%D1%82%D0%BE%D0%B2_(BiCGSTAB)&amp;diff=18054</id>
		<title>Участник:EasyBreezy/Стабилизированный метод бисопряженных градиентов (BiCGSTAB)</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:EasyBreezy/%D0%A1%D1%82%D0%B0%D0%B1%D0%B8%D0%BB%D0%B8%D0%B7%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9_%D0%BC%D0%B5%D1%82%D0%BE%D0%B4_%D0%B1%D0%B8%D1%81%D0%BE%D0%BF%D1%80%D1%8F%D0%B6%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B3%D1%80%D0%B0%D0%B4%D0%B8%D0%B5%D0%BD%D1%82%D0%BE%D0%B2_(BiCGSTAB)&amp;diff=18054"/>
		<updated>2016-11-18T08:47:22Z</updated>

		<summary type="html">&lt;p&gt;Algoman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Основные авторы описания: [[Участник:Novikov alexander|Александр Новиков (1.4, 1.6, 1.7, 2.4, 2.7, 3)]], [[Участник:EasyBreezy|Гаврилов Алексей (1.1 - 1.3, 1.5, 1.8, 1.9, 2.7, 3)]]&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = BiCGSTAB&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt; O(n^2) &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; n &amp;lt;/math&amp;gt; - размерность СЛАУ&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt; O(k*(6 \sqrt n + 4n + 5 \lceil \frac{n}{p} \rceil)) &amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt; 2 \sqrt n &amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = матрица &amp;lt;math&amp;gt;A \in R^{N \times N}&amp;lt;/math&amp;gt; ( &amp;lt;math&amp;gt;C^{N \times N}&amp;lt;/math&amp;gt; ) и вектор правой части &amp;lt;math&amp;gt;b \in R^N&amp;lt;/math&amp;gt; ( &amp;lt;math&amp;gt;C^N&amp;lt;/math&amp;gt; )&lt;br /&gt;
| output_data       = вектор решения системы &amp;lt;math&amp;gt;x \in R^N&amp;lt;/math&amp;gt; ( &amp;lt;math&amp;gt;C^N&amp;lt;/math&amp;gt; )&lt;br /&gt;
}}&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
:Стабилизированный метод бисопряженных градиентов, так же известный как BiCGSTAB (Biconjugate gradient stabilized method), был предложен голландским математиком Хенком ван дер Ворстом&amp;lt;ref&amp;gt;Henk A. vander Vorst, Iterative Krylov Methods for Large Linear Systems, Cambridge University Press 2003, 230p&amp;lt;/ref&amp;gt; в 1992 году. Статья, в которой описывался метод, стала самым цитируемым научным трудом в области математики в 1990х годах.&lt;br /&gt;
&lt;br /&gt;
:Метод появился, как ответ на задачу о построении способа решения систем линейных алгебраических уравнений произвольного вида. На момент появления BiCGSTAB уже существовали методы решения СЛАУ произвольного типа, в том числе и в комплексном пространстве, например метод бисопряженных градиентов. Однако существующие на тот момент методы либо обладали недостаточной скоростью сходимости, либо использовали в вычислениях тяжелые операции, такие как транспонирования матрицы, которые усложняли распараллеливание на многопроцессорных машинах.&lt;br /&gt;
:BiCGSTAB является итерационным методом решения систем линейных алгебраических уравнений. Мощь метода заключается в том, что его можно применять к матрицам общего вида, в том числе с комплексными коэффициентами. В процессе выполнения BiCGSTAB не использует для вычисления плохо распараллеливаемых операций, не допускает накопления погрешностей округления и нестабильного поведения невязки. Эти факторы выгодно отличают его от предшественников: метода бисопряженных градиентов и квадратичного метода сопряженных градиентов, из которого BiCGSTAB фактически и вытекает. К преимуществам так же можно добавить более высокую в общем случае скорость сходимости относительно ближайших конкурентов. Тем не менее, для некоторых видов СЛАУ BiCGSTAB может уступать более простым методам.&amp;lt;ref&amp;gt;Горбаченко В.И, Вычислительная линейная алгебра с примерами на MATLAB. — СПб.: БХВ-Петербург, 2011. — 320 с.: ил. — (Учебное пособие)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Благодаря свойствам алгоритма область применения метода весьма широка. Фактически, он используется во всех задачах, где требуется решать СЛАУ, в том числе СЛАУ большой размерности, к которым сводится большое количество численных методов, применяемых при решении задач математического моделирования. &lt;br /&gt;
&lt;br /&gt;
:BiCGSTAB относится к классу так называемых проекционных методов. Основная идея методов данного класса: искать итерационным способом наилучшее приближение решения в некотором подпространстве пространства &amp;lt;math&amp;gt;R^n&amp;lt;/math&amp;gt;, и чем шире подпространство, в котором ищется приближение решения, тем ближе будет приближенное решение к точному на каждой итерации. В качестве такого подпространства используются пространства Крылова, порожденные матрицей системы и невязкой первого приближения: &amp;lt;math&amp;gt;K^m (A, r^0) = span(r^0, Ar^0, A^2r^0, ..., A^{m-1} r^0).&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;Горбаченко В.И, Вычислительная линейная алгебра с примерами на MATLAB. — СПб.: БХВ-Петербург, 2011. — 320 с.: ил. — (Учебное пособие)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:Изложим основную идею любого проекционного метода, заложенную в том числе и в BiCGSTAB. Для простоты выкладок и рассуждений здесь и далее будем считать, что матрица системы и ее правая часть вещественны. Без ограничения общности все дальнейшие рассуждения могут быть перенесены и на комплексный случай. Итак, пусть решается система &amp;lt;math&amp;gt;Ax=b&amp;lt;/math&amp;gt; с невырожденной матрицей  &amp;lt;math&amp;gt;A \in R^{n \times n}&amp;lt;/math&amp;gt; и ненулевым  вектором  &amp;lt;math&amp;gt;b \in R^n&amp;lt;/math&amp;gt;.  Имеются  два подпространства &amp;lt;math&amp;gt;K_n&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;L_n&amp;lt;/math&amp;gt;. Требуется найти вектор &amp;lt;math&amp;gt;x \in K_n&amp;lt;/math&amp;gt;, который обеспечивает решение  системы, оптимальное относительно подпространства  L, то есть требуется выполнение условия Петрова-Галеркина: &amp;lt;math&amp;gt;(Ax,z)=(b,z), \forall z \in L_n&amp;lt;/math&amp;gt;. В данном случае вектор x называется обобщенным решением системы. &lt;br /&gt;
&lt;br /&gt;
:Условие Петрова-Галеркина можно записать и через определение невязки. Пусть &amp;lt;math&amp;gt;r = b - Ax&amp;lt;/math&amp;gt; - невязка, тогда условие Петрова-Галеркина перепишется в виде: &amp;lt;math&amp;gt;(b - Ax, z)=(r, z),\forall z \in L_n&amp;lt;/math&amp;gt;. Это равносильно тому, что вектор невязки ортогонален пространству &amp;lt;math&amp;gt;L_n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
:Пусть для СЛАУ известно некоторое приближение &amp;lt;math&amp;gt;x^0&amp;lt;/math&amp;gt; точного решения &amp;lt;math&amp;gt;x^*&amp;lt;/math&amp;gt;. Данное приближение требуется уточнить поправкой &amp;lt;math&amp;gt; \delta: b - Ax^0 + \delta \perp L&amp;lt;/math&amp;gt;. Невязка уточненного решения имеет вид: &amp;lt;math&amp;gt;r_{new} = b - Ax^0 + \delta = r^0- A\delta&amp;lt;/math&amp;gt;. Условие Петрова-Галеркина тогда можно переписать так: &amp;lt;math&amp;gt;(r_{new}, z)= r^0 - (A\delta, z) = 0, \forall z \in L&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Пусть  &amp;lt;math&amp;gt; dim K = dim L = m, V = (v_1, ..., v_n) \in R^{n \times m}, W = (w_1, ... w_n) \in R^{n \times m}&amp;lt;/math&amp;gt;, где V и W – матрицы, столбцы которых образуют базисы пространств K и L соответственно. Пусть так же &amp;lt;math&amp;gt; \delta = Vy, z = Wq&amp;lt;/math&amp;gt;, где y – коэффициенты разложения вектора поправки по базису пространства K, а q – коэффициенты разложения вектора z в пространстве L. Тогда новое приближение решения можно записать в виде: &amp;lt;math&amp;gt;x^1 = x^0 + \delta= x^0 + Vy&amp;lt;/math&amp;gt;. Из условия ортогональности Петрова-Галеркина получаем, что: &amp;lt;math&amp;gt;(r - AVy, Wq) = (W^Tr^0 - AVy, q) = 0&amp;lt;/math&amp;gt;. Поскольку &amp;lt;math&amp;gt;q \neq 0&amp;lt;/math&amp;gt;, то получаем СЛАУ для вектора y: &amp;lt;math&amp;gt;W^TAVy = W^Tr^0&amp;lt;/math&amp;gt;. Если предположить, что матрица &amp;lt;math&amp;gt;W^TAVy&amp;lt;/math&amp;gt; невырождена, то вектор y однозначно определяется и равен: &amp;lt;math&amp;gt;y = W^TAV^{-1}W^Tr^0&amp;lt;/math&amp;gt;. Подставляя найденные коэффициенты разложения в выражение для первого приближения получаем: &amp;lt;math&amp;gt;x^1 = x^0 + \delta = x^0 + W^TAV^{-1}W^Tr^0y&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Подведем итог. Общий порядок шагов любого проекционного метода следующий:&lt;br /&gt;
#Выбрать пару подпространств &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt;&lt;br /&gt;
#Найти базис V пространства K и базис W пространства &amp;lt;math&amp;gt;L&amp;lt;/math&amp;gt;;&lt;br /&gt;
#Вычислить невязку&lt;br /&gt;
#Найти &amp;lt;math&amp;gt;y = W^T AV^{-1} W^T r^0&amp;lt;/math&amp;gt;&lt;br /&gt;
#Положить &amp;lt;math&amp;gt;x = x + Vy&amp;lt;/math&amp;gt;&lt;br /&gt;
#Если не достигнут критерий остановки итерационного процесса, то повторить алгоритм, начиная с первого шага.&lt;br /&gt;
&lt;br /&gt;
:Как будет показано далее, в BiCGSTAB не требуется вычислять матрицу  &amp;lt;math&amp;gt;W^T AV^{-1}&amp;lt;/math&amp;gt; в явном виде.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
:Рассмотрим СЛАУ с вещественными коэффициентами:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;Ax = b, A \in R^{N \times N}, b \in R^N&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
:В основу алгоритма ложиться идея проекционного метода и использование свойства A-бисопряженности системы векторов, а именно: векторы &amp;lt;math&amp;gt;p^1, p^2, ...&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\overline p^1, \overline p^2, ...&amp;lt;/math&amp;gt; бисопряжены, если &amp;lt;math&amp;gt;(Ap^i,p^j ) = 0,&amp;lt;/math&amp;gt; при &amp;lt;math&amp;gt;i \neq j&amp;lt;/math&amp;gt;. Фактически, данное условие эквивалентно биортогональности относительно энергетического скалярного произведения. &lt;br /&gt;
 &lt;br /&gt;
:Общая концепция проекционных методов предписывает нам выбрать два подпространства. В нашем случае подпространства мы выберем два подпространства, задаваемые матрицей системы А, вектором невязки на нулевой итерации &amp;lt;math&amp;gt;r^0&amp;lt;/math&amp;gt; и вектором &amp;lt;math&amp;gt;\overline r^0&amp;lt;/math&amp;gt;. который выбирается из условия &amp;lt;math&amp;gt;(r^0, \overline r^0) \neq 0&amp;lt;/math&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;K = K^k(A, r^0), L = K^k(A, \overline r^0)&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Метод основан на построении биортогонального базиса &amp;lt;math&amp;gt;p^0, p^1, ... p^k .. &amp;lt;/math&amp;gt; пространства &amp;lt;math&amp;gt;K^k (A, r^0) &amp;lt;/math&amp;gt; и вычислении поправки такой, что новое приближение на очередной итерации было бы ортогонально второму подпространству Крылова. Базисные вектора строятся до тех пор, пока не будет достигнут критерий остановки итерационного процесса, а каждое последующее приближение формируется, как сумма приближения на предыдущей итерации и найденной поправки. Критерием останова итерационного процесса является достижения невязкой значения, которое меньше некоторого наперед заданного числа &amp;lt;math&amp;gt;\epsilon&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
:Основной итерационный процесс задается формулами:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;x^{k + 1} = x^k + \alpha_k p_k + \omega_k s_k&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;p^{k + 1} = r^{k + 1} + \beta_k p_k - \omega_k Ap_k&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
:где:&lt;br /&gt;
#&amp;lt;math&amp;gt;x^{k + 1}&amp;lt;/math&amp;gt; - приближение на следующей итерации&lt;br /&gt;
#&amp;lt;math&amp;gt;x^k&amp;lt;/math&amp;gt; - приближение на предыдущей итерации&lt;br /&gt;
#&amp;lt;math&amp;gt;p_k&amp;lt;/math&amp;gt; - базисный вектор подпространства Крылова, порожденного матрице СЛАУ и невязкой&lt;br /&gt;
#&amp;lt;math&amp;gt;\alpha_k, \omega_k&amp;lt;/math&amp;gt; - вспомогательные скаляры, определяемые для каждого шага итерации&lt;br /&gt;
#&amp;lt;math&amp;gt;s_k&amp;lt;/math&amp;gt; - вспомогательный вектор&lt;br /&gt;
#&amp;lt;math&amp;gt;p^{k + 1}&amp;lt;/math&amp;gt; - &amp;lt;math&amp;gt;k + 1&amp;lt;/math&amp;gt;-ый базисный вектор&lt;br /&gt;
#&amp;lt;math&amp;gt;r^{k + 1}&amp;lt;/math&amp;gt; - невязка &amp;lt;math&amp;gt;k + 1&amp;lt;/math&amp;gt;-ой итерации&lt;br /&gt;
#&amp;lt;math&amp;gt;\beta_k&amp;lt;/math&amp;gt; - вспомогательный коэффициент&lt;br /&gt;
&lt;br /&gt;
:Вспомогательный вектор выражается следующим образом:&lt;br /&gt;
*&amp;lt;math&amp;gt;s_k = r^k - \alpha_k Ap_k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Вспомогательные коэффициенты вычисляются по формулам:&lt;br /&gt;
*&amp;lt;math&amp;gt;\alpha_k = \frac{(r^k, \overline r^0)}{(Ap_k, \overline r^0)}&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;\omega_k = \frac{(As_k, s_k)}{(As_k, As_k)}&amp;lt;/math&amp;gt;&lt;br /&gt;
*&amp;lt;math&amp;gt;\beta_k = \frac{(r^{k + 1}, \overline r^0)}{(r^k, \overline r^0}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Подведем итог и запишем итерационный процесс&lt;br /&gt;
:Подготовительный этап:&lt;br /&gt;
#Выбирается некоторое начальное приближение &amp;lt;math&amp;gt;x^0&amp;lt;/math&amp;gt;&lt;br /&gt;
#По выбранному приближению находится невязка &amp;lt;math&amp;gt;r^0 = b - Ax^0&amp;lt;/math&amp;gt;&lt;br /&gt;
#Из условия &amp;lt;math&amp;gt;(r^0, \overline r^0) \neq 0&amp;lt;/math&amp;gt; выбирается вектор &amp;lt;math&amp;gt;\overline r^0&amp;lt;/math&amp;gt;&lt;br /&gt;
#Положим &amp;lt;math&amp;gt;p^0 = r^0&amp;lt;/math&amp;gt;&lt;br /&gt;
#Устанавливаем счетчик итераций: &amp;lt;math&amp;gt;n = 0&amp;lt;/math&amp;gt;&lt;br /&gt;
:Итерационный процесс:&lt;br /&gt;
#Находим &amp;lt;math&amp;gt;\alpha_k&amp;lt;/math&amp;gt;&lt;br /&gt;
#По найденному &amp;lt;math&amp;gt;\alpha_k&amp;lt;/math&amp;gt; вычисляем &amp;lt;math&amp;gt;s_k&amp;lt;/math&amp;gt;&lt;br /&gt;
#По найденному &amp;lt;math&amp;gt;s_k&amp;lt;/math&amp;gt; вычисляется вспомогательный коэффициент &amp;lt;math&amp;gt;\omega_k&amp;lt;/math&amp;gt;&lt;br /&gt;
#Находится новое приближение &amp;lt;math&amp;gt;x^{k + 1}&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вычисляется невязка &amp;lt;math&amp;gt;r^{k + 1}&amp;lt;/math&amp;gt;. Если выполнено условие &amp;lt;math&amp;gt;\parallel r^{k + 1} \parallel &amp;lt; \epsilon&amp;lt;/math&amp;gt;, то алгоритм завершается.&lt;br /&gt;
#Вычисляется вспомогательный коэффициент &amp;lt;math&amp;gt;\beta_k&amp;lt;/math&amp;gt;&lt;br /&gt;
#Вычисляется новый базисный вектор: &amp;lt;math&amp;gt;p^{k + 1}&amp;lt;/math&amp;gt;&lt;br /&gt;
#Увеличивается номер итерации: &amp;lt;math&amp;gt;n = n + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
#Переход к первому шагу итерационного процесса.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
:Вычислительное ядро полностью совпадает с итерационным процессом. Подготовка к итерационному процессу в ядро не включается.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
На каждой итерации алгоритма используются:&lt;br /&gt;
# [[Скалярное произведение векторов, вещественная версия, последовательно-параллельный вариант]] x 4 раза&lt;br /&gt;
# [[Умножение плотной матрицы на вектор ]] х 2 раза&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
:Всего в вычислительном блоке алгоритма присутствует 20 трудоемких операций: 2 операции умножения матрицы на вектор, 6 скалярных произведений и 6 сложений/вычитаний векторов и 6 умножений вектора на число.&lt;br /&gt;
&lt;br /&gt;
:Каждое скалярное произведение требует &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; произведений и &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; сложение, то есть &amp;lt;math&amp;gt;2n - 1&amp;lt;/math&amp;gt; операции. Скалярных произведений всего 6 штук (включая поиск нормы), что дает нам &amp;lt;math&amp;gt;12n - 6&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
:Умножение матрицы размерности &amp;lt;math&amp;gt;n \times n&amp;lt;/math&amp;gt; на вектор эквивалентно взятию еще &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; скаляров, и так как таких операций в вычислительном ядре 2, то дополнительно имеется еще &amp;lt;math&amp;gt;2n(2n - 1)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
:Наконец, сложение или вычитание векторов требует &amp;lt;math&amp;gt;6n&amp;lt;/math&amp;gt; соотвествующих операций. Столько же требует 6 произведений вектора на число.&lt;br /&gt;
&lt;br /&gt;
:Итого: &amp;lt;math&amp;gt;2n(2n - 1) + 12n - 6 + 6n + 6n = 4n^2 + 22n - 6&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
:Нетрудоемкие операции, вроде извлечение квадратного корня и деление вещественных чисел друг на друга, не принимаются в расчет, так как они не влияют на итоговый результат. Окончательно можно заключить, что последовательная сложность алгоритма эквивалента &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
[[file:BiCGStabIterations.jpg|thumb|center|800px|&amp;lt;center&amp;gt;Информационный граф.&amp;lt;/center&amp;gt;]]&lt;br /&gt;
На графе представлены связи между операциями, выполняющимися в первых трех итерациях метода. При выполнении большего, чем 3, количества итераций, структура каждой новой будет повторять структуру третьей. Связи между итерациями не представлены, т.к. они не важны для понимания параллельной структуры алгоритма. Серым обозначено перемножение чисел, красным - умножение числа на вектор&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
Основной прирост производительности параллельной версии алгоритма дает использование параллельных операций вычисления скалярного произведения, суммы векторов, а так же произведения матрицы на вектор. Каждая из операций вычисления скалярного произведения и суммы векторов, выполняемая на p процессорах, за счет метода сдваивания может ускориться до &amp;lt;math&amp;gt; \frac{p}{\log_2 p} &amp;lt;/math&amp;gt; раз. Ускорение же умножения матрицы на вектор может достигать p раз.&lt;br /&gt;
&lt;br /&gt;
Ширина и высота ЯПФ графа данного алгоритма напрямую зависит от конкретных реализаций макроопераций и входных данных.&lt;br /&gt;
&lt;br /&gt;
Для последовательно-параллельной реализации операции взятия скалярного произведения в наиболее оптимальном случае (&amp;lt;math&amp;gt;p= \sqrt n&amp;lt;/math&amp;gt;) высота будет равна &amp;lt;math&amp;gt;2 \sqrt n - 1&amp;lt;/math&amp;gt;, а ширина &amp;lt;math&amp;gt;\sqrt n&amp;lt;/math&amp;gt;, где n - это длина вектора решения.&lt;br /&gt;
&lt;br /&gt;
Высота ЯПФ простейшего алгоритма умножения матрицы на вектор равна 2n, а ширина m, где n - это уже упомянутая длина вектора(она же ширина матрицы), а m - высота матрицы.&lt;br /&gt;
&lt;br /&gt;
Высота ЯПФ операции умножения вектора на число = &amp;lt;math&amp;gt;\frac{n}{p}&amp;lt;/math&amp;gt;, а ширина p.&lt;br /&gt;
&lt;br /&gt;
Высота ЯПФ операции вычисления разности векторов = &amp;lt;math&amp;gt; \log_2 p &amp;lt;/math&amp;gt;, а ширина p.&lt;br /&gt;
&lt;br /&gt;
В конечном счете общую высоту ЯПФ одной итерации алгоритма можно оценить, как &amp;lt;math&amp;gt;6 \sqrt n-3 + 4n + 3 + 1 + 3*\lceil \frac{n}{p} \rceil + 2* \lceil \frac{n}{p} \rceil = 6 \sqrt n + 4n + 5 \lceil \frac{n}{p} \rceil + 1&amp;lt;/math&amp;gt;, а ширину, как &amp;lt;math&amp;gt;2 \sqrt n&amp;lt;/math&amp;gt;, если не брать в рассчет проверку критерия сходимости и упрощенности первой итерации по сравнению с остальными.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
:Входные данные&lt;br /&gt;
#Матрица &amp;lt;math&amp;gt;A \in R^{N \times N}&amp;lt;/math&amp;gt; ( &amp;lt;math&amp;gt;C^{N \times N}&amp;lt;/math&amp;gt; )&lt;br /&gt;
#Вектор правой части &amp;lt;math&amp;gt;b \in R^N&amp;lt;/math&amp;gt; ( &amp;lt;math&amp;gt;C^N&amp;lt;/math&amp;gt; )&lt;br /&gt;
&lt;br /&gt;
:Выходные данные:&lt;br /&gt;
#Вектор решения СЛАУ &amp;lt;math&amp;gt;x \in R^N&amp;lt;/math&amp;gt; ( &amp;lt;math&amp;gt;C^N&amp;lt;/math&amp;gt; )&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
:BiCGSTAB хорошо зарекомендовал себя для решения систем линейных алгебраический уравнений, поскольку обладает некоторыми важными свойствами:&lt;br /&gt;
#Благодаря применению подхода Петрова-Галеркина и техники ортогонализации, он численно устойчив&lt;br /&gt;
#Не меняется вид матрицы в процессе решения&lt;br /&gt;
#Эффективен для решения систем большой размерности с разреженной матрицей, поскольку в методе самая трудоемкая операция - умножение матрицы на вектор&lt;br /&gt;
#Лучше подходит под распределенные системы, поскольку не содержит операции транспонирования матрицы&lt;br /&gt;
#Применим для решения систем с несимметричными матрицами.&lt;br /&gt;
#Вычислительная мощность: &amp;lt;math&amp;gt;N/4&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
==== Локальность реализации алгоритма ====&lt;br /&gt;
===== Структура обращений в память и качественная оценка локальности =====&lt;br /&gt;
===== Количественная оценка локальности =====&lt;br /&gt;
===== Анализ на основе теста Apex-Map =====&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
Исследование масштабируемости реализации стабилизированного метода бисопряженных градиентов проводилось согласно [[Scalability methodology|методике]]  на суперкомпьютере &amp;quot;Ломоносов&amp;quot;&amp;lt;ref name=&amp;quot;Lom&amp;quot;&amp;gt;Воеводин Вл., Жуматий С., Соболев С., Антонов А., Брызгалов П., Никитенко Д., Стефанов К., Воеводин Вад. Практика суперкомпьютера «Ломоносов» // Открытые системы, 2012, N 7, С. 36-39.&amp;lt;/ref&amp;gt; [http://parallel.ru/cluster Суперкомпьютерного комплекса Московского университета].&lt;br /&gt;
&lt;br /&gt;
Набор и границы значений изменяемых [[Глоссарий#Параметры запуска|параметров запуска]] реализации алгоритма: &lt;br /&gt;
&lt;br /&gt;
*	число процессоров [4 : 256] с шагом 4;&lt;br /&gt;
*	размер матрицы [1024 : 5120].&lt;br /&gt;
&lt;br /&gt;
В результате проведённых экспериментов был получен следующий диапазон [[Глоссарий#Эффективность реализации|эффективности реализации]] алгоритма:&lt;br /&gt;
&lt;br /&gt;
*	минимальная эффективность реализации 0,11%;&lt;br /&gt;
*	максимальная эффективность реализации 2,65%.&lt;br /&gt;
&lt;br /&gt;
На следующих рисунках приведены графики [[Глоссарий#Производительность|производительности]] и эффективности выбранной реализации стабилизированного метода бисопряженных градиентов в зависимости от изменяемых параметров запуска.&lt;br /&gt;
&lt;br /&gt;
[[file:Масштабируемость параллельной реализации BiCGSTAB Производительность.png|thumb|center|700px|Параллельная реализация стабилизированного метода бисопряженных градиентов. Изменение производительности в зависимости от числа процессоров и размера матрицы.]]&lt;br /&gt;
[[file:Масштабируемость параллельной реализации BiCGSTAB эффективность.png|thumb|center|700px|Параллельная реализация стабилизированного метода бисопряженных градиентов. Изменение эффективности в зависимости от числа процессоров и размера матрицы.]]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/LLNL/hypre/blob/master/src/krylov/HYPRE_bicgstab.c Исследованная параллельная реализация на языке C]&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
* Параллельная реализация алгоритма, предложенная MIT: [http://ab-initio.mit.edu/~meep/meep/src/bicgstab.cpp MIT BiCGSTAB]&lt;br /&gt;
* Параллельная реализация алгоритма в бесплатной библиотеке, поддерживающей MPI и OpenMP, HYPRE: [http://acts.nersc.gov/hypre/ Официальная страница] [https://github.com/LLNL/hypre/blob/master/src/krylov/bicgstab.c Исходный код]&lt;br /&gt;
* Параллельная реализация алгоритма на CUDA в условно бесплатной библиотеке [https://developer.nvidia.com/amgx/ NVIDIA AmgX]&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;/div&gt;</summary>
		<author><name>Algoman</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%D1%86%D1%8B:%D0%90%D0%BB%D0%B5%D0%BA%D1%81%D0%B0%D0%BD%D0%B4%D1%80%D0%B0&amp;diff=17691</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%D1%86%D1%8B:%D0%90%D0%BB%D0%B5%D0%BA%D1%81%D0%B0%D0%BD%D0%B4%D1%80%D0%B0&amp;diff=17691"/>
		<updated>2016-11-16T13:25:42Z</updated>

		<summary type="html">&lt;p&gt;Algoman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Замечания к [[Участник:Александра/Метод_встречи_посередине]] ==&lt;br /&gt;
&lt;br /&gt;
1) отсутствует оценка объёма входных данных на врезке в начале статьи&lt;br /&gt;
&lt;br /&gt;
2) пункты 2.1 и 2.2 должны быть 2.4 и 2.7, согласно формату описания [[Структура_описания_свойств_алгоритмов]]&lt;br /&gt;
&lt;br /&gt;
== Замечания к пункту 2.4 от 16.11.2016 == &lt;br /&gt;
&lt;br /&gt;
* в чём измерялась произвоидтельность в пункте? требуется указать&lt;/div&gt;</summary>
		<author><name>Algoman</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%D1%86%D0%B0:%D0%90%D0%BB%D0%B5%D0%BA%D1%81%D0%B0%D0%BD%D0%B4%D1%80%D0%B0/%D0%9C%D0%B5%D1%82%D0%BE%D0%B4_%D0%B2%D1%81%D1%82%D1%80%D0%B5%D1%87%D0%B8_%D0%BF%D0%BE%D1%81%D0%B5%D1%80%D0%B5%D0%B4%D0%B8%D0%BD%D0%B5&amp;diff=17690</id>
		<title>Участница:Александра/Метод встречи посередине</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D1%86%D0%B0:%D0%90%D0%BB%D0%B5%D0%BA%D1%81%D0%B0%D0%BD%D0%B4%D1%80%D0%B0/%D0%9C%D0%B5%D1%82%D0%BE%D0%B4_%D0%B2%D1%81%D1%82%D1%80%D0%B5%D1%87%D0%B8_%D0%BF%D0%BE%D1%81%D0%B5%D1%80%D0%B5%D0%B4%D0%B8%D0%BD%D0%B5&amp;diff=17690"/>
		<updated>2016-11-16T13:24:17Z</updated>

		<summary type="html">&lt;p&gt;Algoman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Метод встречи посередине&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(\sqrt n\log(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;O(\log(n))&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;\log(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;
Метод &amp;quot;Встреча посередине&amp;quot; криптоанализа блочных шифров был впервые предложен в 1977 году Уитфилдом Диффи и Мартином Хеллманом &amp;lt;ref&amp;gt;(June 1977) «Exhaustive Cryptanalysis of the NBS Data Encryption Standard». Computer 10 (6): 74–84. DOI:10.1109/C-M.1977.217750&amp;lt;/ref&amp;gt;. Встреча посередине используется для ускорения перебора ключей шифра за счёт увеличения требуемой памяти. Метод применим в случае каскадного построения сложного шифра из нескольких простых, другими словами, в случае последовательного применения шифрующих преобразований на разных ключах к блокам открытого текста.&lt;br /&gt;
&lt;br /&gt;
В качестве примера шифра, поддающегося атаке &amp;quot;встреча посередине&amp;quot; можно привести криптоалгоритм 2DES, являющийся модификацией шифра DES. В 2DES открытый текст шифруется дважды алгоритмом DES на двух разных 56-битных ключах. Однако из-за атаки &amp;quot;встреча посередине&amp;quot; сложность перебора двойного ключа (112 бит) шифра 2DES составляет &amp;lt;math&amp;gt;2^{57}&amp;lt;/math&amp;gt; вместо ожидаемых &amp;lt;math&amp;gt;2^{112}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Исходные данные:&#039;&#039;&#039; открытый текст &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;, шифртекст &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Алгоритм зашифрования — композиция двух преобразований &amp;lt;math&amp;gt;T_1(x,k_1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;T_2(x,k_2)&amp;lt;/math&amp;gt;, т.е. &amp;lt;math&amp;gt;y=T_2(T_1(x,k_1),k_2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм расшифрования — &amp;lt;math&amp;gt;y=T_1^{-1}(T_2^{-1}(x,k_2),k_1)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вычисляемые данные:&#039;&#039;&#039; ключи шифрования &amp;lt;math&amp;gt;k_1 \in K_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;k_2 \in K_2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;K_1, K_2&amp;lt;/math&amp;gt; — множества возможных ключей.&lt;br /&gt;
&lt;br /&gt;
Трудоёмкость полного перебора всех возможных пар &amp;lt;math&amp;gt;k_1,k_2&amp;lt;/math&amp;gt; составляет в среднем &amp;lt;math&amp;gt;\frac{|K_1||K_2|}{2}&amp;lt;/math&amp;gt;, а в худшем случае &amp;lt;math&amp;gt;|K_1||K_2|&amp;lt;/math&amp;gt;. Однако используя дополнительную память, можно сократить перебор.&lt;br /&gt;
&lt;br /&gt;
Предположим, что открытый текст &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; и шифртекст &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; однозначно определяют ключи &amp;lt;math&amp;gt;k_1,k_2&amp;lt;/math&amp;gt;. Составим две таблицы:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
z_1 &amp;amp; =T_1(x,k_1^1) &amp;amp; z_1^&#039; &amp;amp;=T_2^{-1}(x,k_2^1)\\\\&lt;br /&gt;
z_2 &amp;amp; =T_1(x,k_1^2) &amp;amp; z_2^&#039; &amp;amp; =T_2^{-1}(x,k_2^2)\\&lt;br /&gt;
... &amp;amp; .................  &amp;amp; ... &amp;amp; .................... \\&lt;br /&gt;
z_{|K_1|} &amp;amp; =T_1(x,k_1^{|K_1|}) &amp;amp; z_{|K_1|}^&#039; &amp;amp; =T_2^{-1}(x,k_2^{|K_1|})&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для всех &amp;lt;math&amp;gt;k_1^i \in K_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;k_2^j \in K_2&amp;lt;/math&amp;gt;. Далее таблицы объединяются и сортируются по значениям &amp;lt;math&amp;gt;z_i,z_j^&#039;&amp;lt;/math&amp;gt;. Индексы &amp;lt;math&amp;gt;i,j&amp;lt;/math&amp;gt;, при которых &amp;lt;math&amp;gt;z_i=z_j^&#039;&amp;lt;/math&amp;gt;, однозначно определяют искомую пару ключей &amp;lt;math&amp;gt;k_1=k_1^i,k_2=k_2^j&amp;lt;/math&amp;gt;. Для нахождения такой пары достаточно просмотреть отсортированную таблицу один раз.&lt;br /&gt;
&lt;br /&gt;
Если же пара открытый текст/шифртекст определяет ключ не единственном образом, то выходом алгоритма будет некоторое множество пар &amp;lt;math&amp;gt;k_1,k_2&amp;lt;/math&amp;gt;, одна из которых является истинным ключом. Для выбора истинного ключа достаточно проверить ключи из полученного множества на других парах открытый текст/шифртекст.&lt;br /&gt;
&lt;br /&gt;
==== Оптимизации ====&lt;br /&gt;
&lt;br /&gt;
1. От генерации второй таблицы со значениями &amp;lt;math&amp;gt;z_j^&#039;&amp;lt;/math&amp;gt; можно отказаться, перебирая ключи &amp;lt;math&amp;gt;k_2^j&amp;lt;/math&amp;gt; до того момента, когда значение &amp;lt;math&amp;gt;z_j^&#039;&amp;lt;/math&amp;gt; совпадёт с одним из значений &amp;lt;math&amp;gt;z_i&amp;lt;/math&amp;gt;. В таком случае опробование ключей &amp;lt;math&amp;gt;k_2^j&amp;lt;/math&amp;gt; в среднем сократится вдвое. Также вдвое сократится объём используемой памяти. Для нахождения совпадающего значения в отсортированном массиве можно применить бинарный поиск.&lt;br /&gt;
&lt;br /&gt;
2. Вместо сортировки таблицы со значениями &amp;lt;math&amp;gt;z_i&amp;lt;/math&amp;gt; и последующего бинарного поиска можно использовать хэш-таблицу.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
В случае использования хэш-таблицы достаточно большого размера основную сложность алгоритма составляет опробование ключей &amp;lt;math&amp;gt;k_1,k_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
Одним из самых трудоёмких шагов также оказывается сортировка таблицы.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Как видно из описания, атака &amp;quot;встреча посередине&amp;quot; использует (или может использовать в качестве оптимизации) следующие алгоритмы:&lt;br /&gt;
&lt;br /&gt;
1. Алгоритм зашифрования/расшифрования&lt;br /&gt;
&lt;br /&gt;
2. Алгоритм сортировки&lt;br /&gt;
&lt;br /&gt;
3. Алгоритмы поиска, вставки в хэш-таблицу&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Далее приводится последовательность действий для варианта алгоритма с генерацией одной таблицы значений &amp;lt;math&amp;gt;z_i&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
1. Вычислить таблицу &amp;lt;math&amp;gt;z_i&amp;lt;/math&amp;gt;, записывая значения в порядке вычисления или используя хэш-таблицу&lt;br /&gt;
&lt;br /&gt;
2. В случае записи значений в порядке вычисления отсортировать массив&lt;br /&gt;
&lt;br /&gt;
3. Опробовать ключи &amp;lt;math&amp;gt;k_2^j&amp;lt;/math&amp;gt;, ища совпадения с таблицей значений &amp;lt;math&amp;gt;z_j^&#039;&amp;lt;/math&amp;gt;. Для нахождения совпадения использовать поиск по хэш-таблице (если она есть) или бинарный поиск&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
Всюду далее считаем, что алгоритм не прекращает работу при нахождении первого совпадения, а ищет все совпадения.&lt;br /&gt;
&lt;br /&gt;
1. Сложность вычисления таблиц значений &amp;lt;math&amp;gt;z_i,z_j^&#039;&amp;lt;/math&amp;gt; составит &amp;lt;math&amp;gt;O(|K_1|+|K_2|)&amp;lt;/math&amp;gt; операций опробования &lt;br /&gt;
&lt;br /&gt;
2. Объединение таблиц и их сортировка будет иметь сложность &amp;lt;math&amp;gt;O((|K_1|+|K_2|)\log(|K_1|+|K_2|))&amp;lt;/math&amp;gt; (например, при сортировке слиянием).&lt;br /&gt;
&lt;br /&gt;
3. Сложность бинарного поиска в отсортированном массиве — &amp;lt;math&amp;gt;O(log_2(|K_1|))&amp;lt;/math&amp;gt; для каждого поиска&lt;br /&gt;
&lt;br /&gt;
4. Сложность поиска в достаточно большой хэш-таблице составит &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt; для каждого поиска&lt;br /&gt;
&lt;br /&gt;
Итого асимптотическая сложность алгоритма:&lt;br /&gt;
&lt;br /&gt;
1. С генерацией двух таблиц — &amp;lt;math&amp;gt;O(|K_1|+|K_2|) + O((|K_1|+|K_2|)\log(|K_1|+|K_2|)) + O(|K_1|+|K_2|)=O((|K_1|+|K_2|)\log(|K_1|+|K_2|))&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. C генерацией одной таблицы, сортировкой и бинарным поиском — &amp;lt;math&amp;gt;O(|K_1|) + O((|K_1|)\log(|K_1|)) + O(|K_2|\log_2(|K_1|))=O(max(|K_1|,|K_2|)\log(|K_1|))&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3. C генерацией одной (достаточно большой) хэш-таблицы — &amp;lt;math&amp;gt;O(|K_1|) + O(|K_2|)=O(|K_1|+|K_2|)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть n - количество всевозможных пар &amp;lt;math&amp;gt;k_1,k_2&amp;lt;/math&amp;gt; и пусть &amp;lt;math&amp;gt;|K_1|=|K_2|&amp;lt;/math&amp;gt;. В этом случае &amp;lt;math&amp;gt;|K_1|=|K_2|=\sqrt n&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Тогда сложность алгоритма в первых двух пунктах составляет &amp;lt;math&amp;gt;O(\sqrt n\log(n))&amp;lt;/math&amp;gt;, в третьем — &amp;lt;math&amp;gt;O(\sqrt n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
&lt;br /&gt;
Опишем информационный граф алгоритма. На вход подаётся открытый (Open) и закрытый (Close), т.е. зашифрованный, текст. Далее открытый текст шифруется (Enc) на ключах &amp;lt;math&amp;gt;k_1^i&amp;lt;/math&amp;gt;, а зашифрованный расшифровывается (Dec) на ключах &amp;lt;math&amp;gt;k_2^j&amp;lt;/math&amp;gt;. Далее полученные криптограммы сравниваются (Cmp) и все ключи, на которых они совпали, являются выходом алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[file:meet.png|thumb|center|900px|Рисунок 1. Граф алгоритма c отображением входных и выходных данных. Open — открытый текст, Close — шифртекст, Enc — операция зашифрования, Dec — операция расшифрования, Cmp — операция сравнения, Keys — вычисленные ключи]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Как видно из информационного графа, для реализации атаки &amp;quot;встреча посередине&amp;quot; в параллельном варианте потребуются выполнение следующих двух ярусов (в предположении, что &amp;lt;math&amp;gt;|K_1|=|K_2|&amp;lt;/math&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
1. &amp;lt;math&amp;gt;\sqrt n&amp;lt;/math&amp;gt; зашифрований и столько же расшифрований&lt;br /&gt;
&lt;br /&gt;
2. &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; сравнений&lt;br /&gt;
&lt;br /&gt;
Таким образом, высота ЯПФ составляет 2, ширина - &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вход:&#039;&#039;&#039;&lt;br /&gt;
На вход подаётся открытый текст &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; и шифртекст &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;, а также алгоритм зашифрования/расшифрования. В случае блочного шифра открытым текстом и шифртекстом является последовательность блоков. Для атаки &amp;quot;встреча посередине&amp;quot;, как правило, берётся один блок для максимального ускорения операций зашифрования и расшифрования.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выход:&#039;&#039;&#039;&lt;br /&gt;
Результатом работы алгоритма является множество пар &amp;lt;math&amp;gt;k_1^i,k_2^j&amp;lt;/math&amp;gt;, для которых нашлись совпадения. Только одна из пар является настоящим ключом. Чтобы отсеять лишние, необходимо проверить все пары на блоках открытого и шифрованного текста, которые в алгоритме не использовались.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
Соотношением последовательной и параллельной сложности алгоритма является &amp;lt;math&amp;gt;O(\sqrt n\log(n))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Будем считать, что размер входных данных (открытый текст и шифртекст) совпадает с размером ключа (на практике это сравнимые величины), а сортировка слиянием делит массивы пополам. Тогда вычислительная мощность алгоритма — &amp;lt;math&amp;gt;O(\sqrt n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Дуги информационного графа, исходящие из вершин зашифрования и расшифрования, образуют пучки мощности &amp;lt;math&amp;gt;\sqrt n&amp;lt;/math&amp;gt;, т.е. из каждой такой вершины выходит &amp;lt;math&amp;gt;\sqrt 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;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
Исследование масштабируемости реализации алгоритма проводилось на суперкомпьютере &amp;quot;Ломоносов&amp;quot;&amp;lt;ref name=&amp;quot;Lom&amp;quot;&amp;gt;Воеводин Вл., Жуматий С., Соболев С., Антонов А., Брызгалов П., Никитенко Д., Стефанов К., Воеводин Вад. Практика суперкомпьютера «Ломоносов» // Открытые системы, 2012, N 7, С. 36-39.&amp;lt;/ref&amp;gt; [http://parallel.ru/cluster Суперкомпьютерного комплекса Московского университета]. Изменяемые параметры запуска:&lt;br /&gt;
* Размер ключа – от 8 до 20 бит с шагом 1&lt;br /&gt;
* Число ядер – от 1 до 8 (значения являются степенью числа 2)&lt;br /&gt;
Ниже представлен график зависимости [[Глоссарий#Производительность|производительности]] от числа ядер и размера ключа (размер задачи – экспоненциальная функция от размера ключа).&lt;br /&gt;
[[File:Масштабируемость.jpg|thumb|center|900px|Рисунок 2. Масштабируемость реализации алгоритма]]&lt;br /&gt;
&lt;br /&gt;
Как видно из графика, производительность почти не изменяется в зависимости от размера задачи, в то время как зависимость производительности от числа ядер визуально близка к линейной. Это связано с тем, что алгоритм содержит большое количество независимых операций опробования ключа, синхронизация между параллельно выполняющимися опробованиями не требуется.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/AlBatarina/Super2016/blob/master/meet_in_the_middle/meet.c Исследованная параллельная реализация на языке C]&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Одна из реализаций атаки &amp;quot;встреча посередине&amp;quot; с использованием хэш-таблицы представлена в свободном доступе по ссылке [https://gist.github.com/dchest/1062437 github]&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;/div&gt;</summary>
		<author><name>Algoman</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:EasyBreezy&amp;diff=17689</id>
		<title>Обсуждение участника:EasyBreezy</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:EasyBreezy&amp;diff=17689"/>
		<updated>2016-11-16T13:21:45Z</updated>

		<summary type="html">&lt;p&gt;Algoman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Замечания к [[Участник:EasyBreezy/Стабилизированный_метод_биспоряженных_градиентов_(BiCGSTAB)]] ==&lt;br /&gt;
&lt;br /&gt;
Все еще отсутствует:&lt;br /&gt;
&lt;br /&gt;
1) пропущен пункт 1.5 &amp;quot;Схема реализации последовательного алгоритма&amp;quot; из-за чего сбита нумерация первой части, см [[Структура_описания_свойств_алгоритмов]]&lt;br /&gt;
&lt;br /&gt;
Пункт пропущен в следствии того, что является избыточным, все шаги по реализации последовательного алгоритма уже содержаться в пункте &amp;quot;Математическое описание&amp;quot;.&lt;br /&gt;
Можем просто повторить содержимое математического описания, но на мой взгляд это не имеет смысла&lt;br /&gt;
&lt;br /&gt;
[[Участник:Algoman|Algoman]] ([[Обсуждение участника:Algoman|обсуждение]]) 16:21, 16 ноября 2016 (MSK)&lt;br /&gt;
Пункт 1.5 не является избыточным - в нём более описывается то же, что в и 1.2, но боллее схематично и наглядно для беглого восприятия: в виде псевдокода/блок схема. Дублирование не нужно. Даже в случае его умышленного пропуска нумерация пунктов не должна быть сбита.&lt;br /&gt;
&lt;br /&gt;
== Замечания к пункту 2.4 от 16.11.2016 == &lt;br /&gt;
&lt;br /&gt;
* картинки не работают&lt;br /&gt;
* какие выводы можно сделать о масштабируемости алгоритма, исходя из полученных данных? Требуется явно написать это в пункте.&lt;/div&gt;</summary>
		<author><name>Algoman</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:EasyBreezy&amp;diff=17688</id>
		<title>Обсуждение участника:EasyBreezy</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:EasyBreezy&amp;diff=17688"/>
		<updated>2016-11-16T13:15:35Z</updated>

		<summary type="html">&lt;p&gt;Algoman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Замечания к [[Участник:EasyBreezy/Стабилизированный_метод_биспоряженных_градиентов_(BiCGSTAB)]] ==&lt;br /&gt;
&lt;br /&gt;
Все еще отсутствует:&lt;br /&gt;
&lt;br /&gt;
1) пропущен пункт 1.5 &amp;quot;Схема реализации последовательного алгоритма&amp;quot; из-за чего сбита нумерация первой части, см [[Структура_описания_свойств_алгоритмов]]&lt;br /&gt;
&lt;br /&gt;
Пункт пропущен в следствии того, что является избыточным, все шаги по реализации последовательного алгоритма уже содержаться в пункте &amp;quot;Математическое описание&amp;quot;.&lt;br /&gt;
Можем просто повторить содержимое математического описания, но на мой взгляд это не имеет смысла&lt;/div&gt;</summary>
		<author><name>Algoman</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:Sergey_Lavrushkin/EM-%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8&amp;diff=17686</id>
		<title>Участник:Sergey Lavrushkin/EM-алгоритм кластеризации</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:Sergey_Lavrushkin/EM-%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8&amp;diff=17686"/>
		<updated>2016-11-16T13:04:54Z</updated>

		<summary type="html">&lt;p&gt;Algoman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = EM-алгоритм кластеризации (1 итерация)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(nkq^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(\log{nk})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(nk)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;nq + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;k(n + q^2 + q + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
Автор статьи: [[Участник: Sergey Lavrushkin|Сергей Лаврушкин]] (группа 620)&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
==== EM-алгоритм ====&lt;br /&gt;
EM-алгоритм (англ. expectation-maximization) — алгоритм, используемый в математической статистике для нахождения оценок максимального правдоподобия параметров вероятностных моделей, в случае, когда модель зависит от некоторых скрытых переменных. Каждая итерация алгоритма состоит из двух шагов. На E-шаге (expectation) вычисляется ожидаемое значение функции правдоподобия, при этом скрытые переменные рассматриваются как наблюдаемые. На M-шаге (maximization) вычисляется оценка максимального правдоподобия, таким образом увеличивается ожидаемое правдоподобие, вычисляемое на E-шаге. Затем это значение используется для E-шага на следующей итерации. Алгоритм выполняется до сходимости.&amp;lt;ref&amp;gt;ЕМ-алгоритм, его модификации и обобщения [http://www.machinelearning.ru/wiki/index.php?title=EM-%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC http://www.machinelearning.ru/wiki/index.php?title=EM-алгоритм]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Как правило, ЕМ-алгоритм применяется для решения задач двух типов:&lt;br /&gt;
* К первому типу можно отнести задачи, связанные с анализом действительно неполных данных, когда некоторые статистические данные отсутствуют в силу каких-либо причин.&lt;br /&gt;
* Ко второму типу задач можно отнести те задачи, в которых функция правдоподобия имеет вид, не допускающий удобных аналитических методов исследования, но допускающий серьезные упрощения, если в задачу ввести дополнительные «ненаблюдаемые» (скрытые, латентные) переменные. Примерами прикладных задач второго типа являются задачи распознавания образов, реконструкции изображений. Математическую суть данных задач составляют задачи кластерного анализа, классификации и разделения смесей вероятностных распределений.&lt;br /&gt;
&lt;br /&gt;
Алгоритм основан на методике итеративного вычисления оценок максимального правдоподобия, предложенной в 1977 г. (A. P. Demster, N. M. Laird, D. B. Rubin. Maximum Likelihood from Incomplete Data via the EM Algorithm).&amp;lt;ref&amp;gt; A. Dempster, N. Laird and D. Rubin. Maximum likelihood estimation from incomplete data. – Journal of the Royal Statistical Society, Series B, 1977, vol. 39, p. 1-38.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Кластеризация с помощью EM-алгоритма ====&lt;br /&gt;
&lt;br /&gt;
Кластеризация — задача разбиения заданной выборки объектов (ситуаций) на непересекающиеся подмножества, называемые кластерами, так, чтобы каждый кластер состоял из схожих объектов, а объекты разных кластеров существенно отличались &amp;lt;ref&amp;gt;Кластеризация [http://www.machinelearning.ru/wiki/index.php?title=%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F http://www.machinelearning.ru/wiki/index.php?title=Кластеризация]&amp;lt;/ref&amp;gt;. В основе идеи применения EM-алгоритма для кластеризации лежит предположение, что исследуемое множество данных может быть смоделировано с помощью линейной комбинации многомерных нормальных распределений, а целью является оценка параметров распределения, которые максимизируют логарифмическую функцию правдоподобия, используемую в качестве меры качества модели. К оцениваемым параметрам относятся математические ожидания и ковариационные матрицы. Предполагается, что любое наблюдение принадлежит ко всем кластерам, но с разной вероятностью. Задача заключается в &amp;quot;подгонке&amp;quot; распределений смеси к данным, а затем в определении вероятностей принадлежности наблюдения к каждому кластеру. Наблюдение должно быть отнесено к тому кластеру, для которого данная вероятность выше.&lt;br /&gt;
&lt;br /&gt;
Алгоритм EM основан на вычислении расстояний. Он может рассматриваться как обобщение кластеризации на основе анализа смеси вероятностных распределений. В процессе работы алгоритма происходит итеративное улучшение решения, а остановка осуществляется в момент, когда достигается требуемый уровень точности модели. Мерой в данном случае является монотонно увеличивающаяся статистическая величина, называемая логарифмическим правдоподобием.&amp;lt;ref&amp;gt;EМ — масштабируемый алгоритм кластеризации [https://basegroup.ru/community/articles/em https://basegroup.ru/community/articles/em]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
Исходные данные: &lt;br /&gt;
* &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; — число кластеров,&lt;br /&gt;
* &amp;lt;math&amp;gt;X =\{x_{1}, x_{2}, ..., x_{n}\}&amp;lt;/math&amp;gt; — множество из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; наблюдений размерности &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;x_{i} = (x_{i1}, ..., x_{iq})&amp;lt;/math&amp;gt;.&lt;br /&gt;
Вычисляемые данные:&lt;br /&gt;
* &amp;lt;math&amp;gt;(w, \theta) = (w_1, ..., w_k; \mu_1, ..., \mu_k; \Sigma_1, ..., \Sigma_k)&amp;lt;/math&amp;gt; — параметры смеси гауссовых распределений,&lt;br /&gt;
* &amp;lt;math&amp;gt;Y&amp;lt;/math&amp;gt; — матрица размера &amp;lt;math&amp;gt;n \times k&amp;lt;/math&amp;gt; с вероятностями членства в кластерах.&lt;br /&gt;
==== Постановка задачи разделения смеси гауссовых распределений ====&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;w_1, ..., w_k&amp;lt;/math&amp;gt; — априорные вероятности кластеров, &amp;lt;math&amp;gt;p_1(x), ..., p_k(x)&amp;lt;/math&amp;gt; — плотности распределения кластеров.&lt;br /&gt;
Тогда плотность распределения вектора признаков &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; сразу по всем кластерам равна:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
p(x) = \sum_{j=1}^{k}w_jp_j(x)&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Необходимо на основе выборки оценить параметры модели &amp;lt;math&amp;gt;w_1, ..., w_k, p_1(x), ..., p_k(x)&amp;lt;/math&amp;gt;. Это позволит оценивать вероятность принадлежности к кластеру и, таким образом, решить задачу кластеризации. Такая задача&lt;br /&gt;
называется задачей разделения смеси распределений:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
p(x) = \sum_{j=1}^{k}w_jp_j(x),\quad p_j(x) = \phi(\theta_j; x),&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где &amp;lt;math&amp;gt;\theta_j&amp;lt;/math&amp;gt; — параметры распределения &amp;lt;math&amp;gt;p_j(x)&amp;lt;/math&amp;gt;.&lt;br /&gt;
В случае смеси гауссовых распределений в &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt;-мерном пространстве признаков &amp;lt;math&amp;gt;\phi(\theta_j; x)&amp;lt;/math&amp;gt; имеют следующий вид:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\phi(\theta_j; x) = \frac{1}{\Big(2\pi\Big)^{\frac{q}{2}}\sqrt{|\Sigma_j|}}\exp{\bigg\{-\frac{\delta^2}{2}\bigg\} }, &lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где:&lt;br /&gt;
* &amp;lt;math&amp;gt;\Sigma_j&amp;lt;/math&amp;gt; — ковариационная матрица размером &amp;lt;math&amp;gt;q \times q&amp;lt;/math&amp;gt;,&lt;br /&gt;
* &amp;lt;math&amp;gt;\mu_j&amp;lt;/math&amp;gt; — &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt;-мерный вектор математических ожиданий,&lt;br /&gt;
* &amp;lt;math&amp;gt;\delta^2 = \Big( x - \mu_j \Big)^T \Sigma_j^{-1} \Big( x - \mu_j \Big)&amp;lt;/math&amp;gt; — квадратичное расстояние Махаланобиса.&lt;br /&gt;
В случае смеси гауссовых распределений получаем, что &amp;lt;math&amp;gt;\theta_j = (\mu_j, \Sigma_j)&amp;lt;/math&amp;gt;. То есть для решения задачи разделения смеси гауссовых распределений необходимо оценить вектор параметров &amp;lt;math&amp;gt;(w, \theta) = (w_1, ..., w_k; \mu_1, ..., \mu_k; \Sigma_1, ..., \Sigma_k)&amp;lt;/math&amp;gt;. Согласно принципу максимизации правдоподобия:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
w, \theta = \underset{w, \theta}{\operatorname{argmax}} \sum_{i=1}^{n}\ln{p(x_i)} = \underset{w, \theta}{\operatorname{argmax}} \sum_{i=1}^{n}\ln{\sum_{j=1}^{k}w_jp_j(x_i)}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Таким образом, имеет место задача максимизации суммы логарифмов сумм, решение которой представляет большую трудность. В таком случае полезным оказывается итеративный метод решения — EM-алгоритм.&amp;lt;ref&amp;gt;Поиск структуры в данных — Lecture 9 — Expectation Maximization (EM-алгоритм) [https://www.coursera.org/learn/unsupervised-learning/lecture/2jhbI/expectation-maximization-em-alghoritm https://www.coursera.org/learn/unsupervised-learning/lecture/2jhbI/expectation-maximization-em-alghoritm]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== EM-алгоритм ====&lt;br /&gt;
Оптимальные параметры задачи разделения смеси гауссовых распределений отыскиваются последовательно с помощью итерационного EM-алгоритма. Основная идея – вводится вспомогательный вектор скрытых переменных. Это позволяет свести сложную оптимизационную задачу к последовательности итераций по пересчету коэффициентов (скрытых переменных по текущему приближению вектора параметров - E-шаг) и максимизации правдоподобия (с целью найти следующее приближение вектора - М-шаг).&amp;lt;ref&amp;gt;EM алгоритм (пример) [http://www.machinelearning.ru/wiki/index.php?title=EM_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_(%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80) http://www.machinelearning.ru/wiki/index.php?title=EM_алгоритм_(пример)]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
EM-алгоритм заключается в следующем:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; В начале работы алгоритма задаются параметры начального приближения. Наиболее общим способом инициализации является присвоение элементам матрицы математических ожиданий случайных значений &amp;lt;math&amp;gt; \mu_j \leftarrow Random &amp;lt;/math&amp;gt;, начальные ковариационные матрицы определяются как единичные &amp;lt;math&amp;gt;\Sigma_j \leftarrow I&amp;lt;/math&amp;gt;, веса кластеров задаются одинаковыми &amp;lt;math&amp;gt;w_i \leftarrow \frac{1}{k}&amp;lt;/math&amp;gt;. Также в качестве начальных параметров можно использовать результат работы алгоритма K-means. (Данная эвристика применяется, так как K-means требуется намного меньше итераций до достижения стабилизации, в то время как каждый шаг EM требует больших вычислительных затрат).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Далее итеративно выполняется следующая пара процедур:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;E-шаг: используя текущее значение вектора параметров &amp;lt;math&amp;gt;(w, \theta) = (w_1, ..., w_k; \mu_1, ..., \mu_k; \Sigma_1, ..., \Sigma_k)&amp;lt;/math&amp;gt;, вычисляются значения скрытых переменных &amp;lt;math&amp;gt;y_{ij}&amp;lt;/math&amp;gt;:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
&amp;amp; y_{ij} = \frac{w_j p_j(x_i)}{\sum_{l=1}^{k}w_lp_l(x_i)}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;М-шаг: переоценка вектора параметров, используя текущие значения скрытых переменных:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
&amp;amp; n_j = \sum_{i = 1}^{n}y_{ij}, \\&lt;br /&gt;
&amp;amp; \mu_j^{new} = \frac{1}{n_j} \sum_{i = 1}^{n}y_{ij}x_i, \\&lt;br /&gt;
&amp;amp; \Sigma_j^{new} = \frac{1}{n_j} \sum_{i = 1}^{n}y_{ij}(x_i - \mu_j^{new})(x_i - \mu_j^{new})^T,\\&lt;br /&gt;
&amp;amp; w_j^{new} = \frac{n_j}{n}.&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
Итерации происходят до сходимости (норма разности векторов скрытых переменных или изменение логарифмического правдоподобия на каждой итерации не будет превышать заданную константу) или достижения максимального числа итераций.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
В вычислительное ядро EM-алгоритма входят:&lt;br /&gt;
* Вычисление скрытых переменных &amp;lt;math&amp;gt;y_{ij}&amp;lt;/math&amp;gt; на E-шаге (всего их &amp;lt;math&amp;gt;nk&amp;lt;/math&amp;gt;).&lt;br /&gt;
* Переоценка вектора параметров &amp;lt;math&amp;gt;(w_1, ..., w_k; \mu_1, ..., \mu_k; \Sigma_1, ..., \Sigma_k)&amp;lt;/math&amp;gt; на M-шаге, используя текущие значения скрытых переменных &amp;lt;math&amp;gt;y_{ij}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Как записано в описании ядра алгоритма, основную часть метода составляют множественные вычисления скрытых переменных &amp;lt;math&amp;gt;y_{ij}&amp;lt;/math&amp;gt; на E-шаге и обновление вектора параметров &amp;lt;math&amp;gt;(w_1, ..., w_k; \mu_1, ..., \mu_k; \Sigma_1, ..., \Sigma_k)&amp;lt;/math&amp;gt; на M-шаге.&lt;br /&gt;
Также стоит выделить вычисление определителя и обратной матрицы ковариационных матриц &amp;lt;math&amp;gt;\Sigma_j&amp;lt;/math&amp;gt; в начале E-шага.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Последовательная реализация алгоритма EM может быть проиллюстрирована с помощью следующего псевдокода:&lt;br /&gt;
# &#039;&#039;&#039;Инициализация&#039;&#039;&#039;: установка начальных значений &amp;lt;math&amp;gt;\mu, \, \Sigma_j \, (j = \overline{1, k}), \, w&amp;lt;/math&amp;gt;.&lt;br /&gt;
# &#039;&#039;&#039;Пока&#039;&#039;&#039; изменение логарифмического правдоподобия &amp;lt;math&amp;gt;\Delta llh \geq \epsilon&amp;lt;/math&amp;gt; и не достигнуто максимальное число итераций &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, &#039;&#039;&#039;выполнять&#039;&#039;&#039; шаги E и M.&lt;br /&gt;
&#039;&#039;&#039;Шаг E&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;def&#039;&#039;&#039; E-step:&lt;br /&gt;
     &#039;&#039;&#039;Инициализировать&#039;&#039;&#039; нулевыми значениями &amp;lt;math&amp;gt;\mu^{&#039;}, \, \Sigma_j^{&#039;} \, (j = \overline{1, k}), \, w^{&#039;}, \, llh&amp;lt;/math&amp;gt;&lt;br /&gt;
     &#039;&#039;&#039;for&#039;&#039;&#039; &amp;lt;math&amp;gt;j = \overline{1, k}&amp;lt;/math&amp;gt;:&lt;br /&gt;
         &#039;&#039;&#039;Вычислить&#039;&#039;&#039; определитель и обратную матрицу матрицы &amp;lt;math&amp;gt;\Sigma_j&amp;lt;/math&amp;gt;&lt;br /&gt;
     &#039;&#039;&#039;for&#039;&#039;&#039; &amp;lt;math&amp;gt;i = \overline{1, n}&amp;lt;/math&amp;gt;:&lt;br /&gt;
         &amp;lt;math&amp;gt;sump_i = 0&amp;lt;/math&amp;gt;&lt;br /&gt;
         &#039;&#039;&#039;for&#039;&#039;&#039; &amp;lt;math&amp;gt;j = \overline{1, k}&amp;lt;/math&amp;gt;:&lt;br /&gt;
             &amp;lt;math&amp;gt;\delta_{ij}^2 = \big( x_i - \mu_j \big)^T \Sigma_j^{-1} \big( x_i - \mu_j \big)&amp;lt;/math&amp;gt;&lt;br /&gt;
             &amp;lt;math&amp;gt;g_{ij} = \frac{w_j}{{(2 \pi)}^\frac{q}{2}\sqrt{|\Sigma_j|}}\exp{\big\{-\frac{\delta_{ij}^2}{2}\big\} }&amp;lt;/math&amp;gt;&lt;br /&gt;
             &amp;lt;math&amp;gt;sump_i \mathrel{+}= g_{ij}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;y_i = \frac{g_i}{sump_i}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;llh \mathrel{+}= \ln(sump_i)&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mu^{&#039;} \mathrel{+}= x_iy_i^T&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;w^{&#039;} \mathrel{+}= y_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Шаг M&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;def&#039;&#039;&#039; M-step:&lt;br /&gt;
     &#039;&#039;&#039;for&#039;&#039;&#039; &amp;lt;math&amp;gt;j = \overline{1, k}&amp;lt;/math&amp;gt;:&lt;br /&gt;
         &amp;lt;math&amp;gt;\mu_j = \frac{\mu_j^{&#039;}}{w_j^{&#039;}}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &#039;&#039;&#039;for&#039;&#039;&#039; &amp;lt;math&amp;gt;i = \overline{1, n}&amp;lt;/math&amp;gt;:&lt;br /&gt;
             &amp;lt;math&amp;gt;\Sigma_j^{&#039;} \mathrel{+}= (x_i - \mu_j)y_{ij}(x_i - \mu_j)^T&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\Sigma_j = \frac{\Sigma_j^{&#039;}}{w_j^{&#039;}}&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;w = \frac{w^{&#039;}}{n}&amp;lt;/math&amp;gt;&lt;br /&gt;
Логаририфмическое правдоподобие вычисляется как:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
llh=\sum_{i=1}^{n}\ln{(sump_i)}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Матрицы &amp;lt;math&amp;gt;\mu^{&#039;}, \, \Sigma_j^{&#039;} \, (j = \overline{1, k}), \, w^{&#039;}&amp;lt;/math&amp;gt; являются временными и используются только для вычислений.&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
Последовательная сложность одной итерации EM-алгоритма:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; E-шаг: &amp;lt;br&amp;gt;&lt;br /&gt;
В случае недиагональных ковариационных матриц сложность вычислений:&lt;br /&gt;
* Определителей ковариационных матриц &amp;lt;math&amp;gt;|\Sigma_j|&amp;lt;/math&amp;gt; (&amp;lt;math&amp;gt;j = \overline{1, k}&amp;lt;/math&amp;gt;) методом Гаусса: &amp;lt;math&amp;gt;O(kq^3)&amp;lt;/math&amp;gt;,&lt;br /&gt;
* Матриц, обратных ковариационным матрицам &amp;lt;math&amp;gt;\Sigma_j^{-1}&amp;lt;/math&amp;gt; (&amp;lt;math&amp;gt;j = \overline{1, k}&amp;lt;/math&amp;gt;) методом Гаусса-Жордана: &amp;lt;math&amp;gt;O(kq^3)&amp;lt;/math&amp;gt;,&lt;br /&gt;
* Скрытых переменных &amp;lt;math&amp;gt;y_{ij}&amp;lt;/math&amp;gt; (&amp;lt;math&amp;gt;i = \overline{1, n}, j = \overline{1, k}&amp;lt;/math&amp;gt;): &amp;lt;math&amp;gt;O(nkq^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
В случае диагональных ковариационных матриц сложность вычислений:&lt;br /&gt;
* Определителей ковариационных матриц &amp;lt;math&amp;gt;|\Sigma_j|&amp;lt;/math&amp;gt; (&amp;lt;math&amp;gt;j = \overline{1, k}&amp;lt;/math&amp;gt;): &amp;lt;math&amp;gt;O(kq)&amp;lt;/math&amp;gt;,&lt;br /&gt;
* Матриц, обратных ковариационным матрицам &amp;lt;math&amp;gt;\Sigma_j^{-1}&amp;lt;/math&amp;gt; (&amp;lt;math&amp;gt;j = \overline{1, k}&amp;lt;/math&amp;gt;): &amp;lt;math&amp;gt;O(kq)&amp;lt;/math&amp;gt;,&lt;br /&gt;
* Скрытых переменных &amp;lt;math&amp;gt;y_{ij}&amp;lt;/math&amp;gt; (&amp;lt;math&amp;gt;i = \overline{1, n}, j = \overline{1, k}&amp;lt;/math&amp;gt;): &amp;lt;math&amp;gt;O(nkq)&amp;lt;/math&amp;gt;.&lt;br /&gt;
Получаем, что последовательная сложность E-шага в случае недиагональных ковариационных матриц имеет порядок &amp;lt;math&amp;gt;O(kq^3 + nkq^2)&amp;lt;/math&amp;gt;, а в случае диагональных ковариационных матриц — &amp;lt;math&amp;gt;O(nkq)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&lt;br /&gt;
М-шаг: &amp;lt;br&amp;gt;&lt;br /&gt;
В случае недиагональных ковариационных матриц сложность вычислений:&lt;br /&gt;
* Обновление математических ожиданий &amp;lt;math&amp;gt;\mu_j&amp;lt;/math&amp;gt; (&amp;lt;math&amp;gt;j = \overline{1, k}&amp;lt;/math&amp;gt;): &amp;lt;math&amp;gt;O(nkq)&amp;lt;/math&amp;gt;,&lt;br /&gt;
* Обновление ковариационных матриц &amp;lt;math&amp;gt;\Sigma_j&amp;lt;/math&amp;gt; (&amp;lt;math&amp;gt;j = \overline{1, k}&amp;lt;/math&amp;gt;): &amp;lt;math&amp;gt;O(nkq^2)&amp;lt;/math&amp;gt;,&lt;br /&gt;
* Обновление весов кластеров &amp;lt;math&amp;gt;w_j&amp;lt;/math&amp;gt; (&amp;lt;math&amp;gt;j = \overline{1, k}&amp;lt;/math&amp;gt;): &amp;lt;math&amp;gt;O(nk)&amp;lt;/math&amp;gt;.&lt;br /&gt;
В случае диагональных ковариационных матриц сложность вычислений:&lt;br /&gt;
* Обновление математических ожиданий &amp;lt;math&amp;gt;\mu_j&amp;lt;/math&amp;gt; (&amp;lt;math&amp;gt;j = \overline{1, k}&amp;lt;/math&amp;gt;): &amp;lt;math&amp;gt;O(nkq)&amp;lt;/math&amp;gt;,&lt;br /&gt;
* Обновление ковариационных матриц &amp;lt;math&amp;gt;\Sigma_j&amp;lt;/math&amp;gt; (&amp;lt;math&amp;gt;j = \overline{1, k}&amp;lt;/math&amp;gt;): &amp;lt;math&amp;gt;O(nkq)&amp;lt;/math&amp;gt;,&lt;br /&gt;
* Обновление весов кластеров &amp;lt;math&amp;gt;w_j&amp;lt;/math&amp;gt; (&amp;lt;math&amp;gt;j = \overline{1, k}&amp;lt;/math&amp;gt;): &amp;lt;math&amp;gt;O(nk)&amp;lt;/math&amp;gt;.&lt;br /&gt;
Получаем, что последовательная сложность М-шага в случае недиагональных ковариационных матриц имеет порядок &amp;lt;math&amp;gt;O(nkq^2)&amp;lt;/math&amp;gt;, а в случае диагональных ковариационных матриц — &amp;lt;math&amp;gt;O(nkq)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
Таким образом, последовательная сложность итерации EM-алгоритма в случае недиагональных ковариационных матриц имеет порядок &amp;lt;math&amp;gt;O(kq^3 + nkq^2)&amp;lt;/math&amp;gt;, а в случае диагональных ковариационных матриц — &amp;lt;math&amp;gt;O(nkq)&amp;lt;/math&amp;gt;. При этом, обычно размерность элементов выборки &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt;, также как и число кластеров &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;, значительно меньше числа элементов выборки &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; (&amp;lt;math&amp;gt;k \ll n, q \ll n&amp;lt;/math&amp;gt;), поэтому в случае недиагональных ковариационных матриц сложность может быть записана в виде &amp;lt;math&amp;gt;O(nkq^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
&lt;br /&gt;
Граф алгоритма в терминах E-шагов и M-шагов представлен на рис. 1. Каждая итерация алгоритма зависит от результата работы предыдущей итерации, M-шаг зависит от результата E-шага.&lt;br /&gt;
&lt;br /&gt;
[[Файл:EM-alg-Lavrushkin.png|thumb|1000px|center|Рисунок 1. Граф EM-алгоритма. &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; — число кластеров; &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; — множество наблюдений; &amp;lt;math&amp;gt;Y&amp;lt;/math&amp;gt; — матрица с вероятностями членства в кластерах.]]&lt;br /&gt;
&lt;br /&gt;
Рассмотрим по отдельности информационные графы E-шага и M-шага.&lt;br /&gt;
&lt;br /&gt;
==== E-шаг ====&lt;br /&gt;
Опишем граф E-шага как аналитически, так и в виде рисунка.&lt;br /&gt;
&lt;br /&gt;
Граф алгоритма состоит из четырех групп вершин:&lt;br /&gt;
*&#039;&#039;&#039;Первая&#039;&#039;&#039; группа вершин соответствует вычислению обратных матриц и определителей ковариационных матриц. Число вершин: &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;. Аргументом этой операции является ковариационная матрица &amp;lt;math&amp;gt;\Sigma_j&amp;lt;/math&amp;gt;. Результат срабатывания операции является промежуточным данным алгоритма.&lt;br /&gt;
*&#039;&#039;&#039;Вторая&#039;&#039;&#039; группа вершин соответствует вычислению &amp;lt;math&amp;gt;g_{ij} = \frac{w_j}{{2 \pi}^\frac{q}{2}|\Sigma_j|}\exp{\big\{-\frac{1}{2}  \big( x_i - \mu_j \big)^T \Sigma_j^{-1} \big( x_i - \mu_j \big)  \big\}}&amp;lt;/math&amp;gt;. Число вершин: &amp;lt;math&amp;gt;nk&amp;lt;/math&amp;gt;. Аргументами этой операции являются вес кластера &amp;lt;math&amp;gt;w_j&amp;lt;/math&amp;gt;, математическое ожидание &amp;lt;math&amp;gt;\mu_j&amp;lt;/math&amp;gt;, ковариационная матрица &amp;lt;math&amp;gt;\Sigma_j&amp;lt;/math&amp;gt;, элемент выборки &amp;lt;math&amp;gt;x_i&amp;lt;/math&amp;gt;. Результат срабатывания операции является промежуточным данным алгоритма.&lt;br /&gt;
*&#039;&#039;&#039;Третья&#039;&#039;&#039; группа вершин соответствует вычислению нормировочных коэффициентов &amp;lt;math&amp;gt;\sum_{l=1}^{k}g_{ij}&amp;lt;/math&amp;gt;. Число вершин: &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;. Аргументами этой операции являются значения &amp;lt;math&amp;gt;g_{ij}, \, j = \overline{1, k}&amp;lt;/math&amp;gt;. Результат срабатывания операции является промежуточным данным алгоритма.&lt;br /&gt;
*&#039;&#039;&#039;Четвертая&#039;&#039;&#039; группа вершин соответствует вычислению скрытых переменных &amp;lt;math&amp;gt;y_{ij}&amp;lt;/math&amp;gt;. Число вершин: &amp;lt;math&amp;gt;nk&amp;lt;/math&amp;gt;. Аргументами этой операции являются значение &amp;lt;math&amp;gt;g_{ij}&amp;lt;/math&amp;gt; и нормировочный коэффициент. Результат срабатывания операции является выходным данным алгоритма.&lt;br /&gt;
&lt;br /&gt;
Описанный граф представлен на рис.2 и рис.3. Здесь вершины одной группы расположены в одной строке. Вершины-операции обозначены синим цветом, вершины-данные — оранжевым.&lt;br /&gt;
&lt;br /&gt;
[[Файл:E-step-Lavrushkin.png|thumb|1000px|center|Рисунок 2. Граф E-шага.]]&lt;br /&gt;
[[Файл:E-step2-Lavrushkin.png|thumb|800px|center|Рисунок 3. Граф E-шага с с отображением входных и выходных данных.]]&lt;br /&gt;
&lt;br /&gt;
==== M-шаг ====&lt;br /&gt;
Опишем граф M-шага как аналитически, так и в виде рисунка.&lt;br /&gt;
&lt;br /&gt;
Граф алгоритма состоит из четырех групп вершин:&lt;br /&gt;
*&#039;&#039;&#039;Первая&#039;&#039;&#039; группа вершин соответствует вычислению нормировочных коэффициентов &amp;lt;math&amp;gt;n_j&amp;lt;/math&amp;gt;. Число вершин: &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;. Аргументами этой операции являются скрытые переменные &amp;lt;math&amp;gt;y_{ij}, \, i = \overline{1, n}&amp;lt;/math&amp;gt;. Результат срабатывания операции является промежуточным данным алгоритма.&lt;br /&gt;
*&#039;&#039;&#039;Вторая&#039;&#039;&#039; группа вершин соответствует вычислению математических ожиданий &amp;lt;math&amp;gt;\mu_j&amp;lt;/math&amp;gt;. Число вершин: &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;. Аргументами этой операции являются множество наблюдений &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt;, скрытые переменные &amp;lt;math&amp;gt;y_{ij}, \, i = \overline{1, n}&amp;lt;/math&amp;gt;, нормировочный коэффициент &amp;lt;math&amp;gt;n_j&amp;lt;/math&amp;gt;. Результат срабатывания операции является выходным данным алгоритма.&lt;br /&gt;
*&#039;&#039;&#039;Третья&#039;&#039;&#039; группа вершин соответствует вычислению ковариационных матриц &amp;lt;math&amp;gt;\Sigma_j&amp;lt;/math&amp;gt;. Число вершин: &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;. Аргументами этой операции являются множество наблюдений &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt;, скрытые переменные &amp;lt;math&amp;gt;y_{ij}, \, i = \overline{1, n}&amp;lt;/math&amp;gt;, нормировочный коэффициент &amp;lt;math&amp;gt;n_j&amp;lt;/math&amp;gt;, математическое ожидание &amp;lt;math&amp;gt;\mu_j&amp;lt;/math&amp;gt;. Результат срабатывания операции является выходным данным алгоритма.&lt;br /&gt;
*&#039;&#039;&#039;Четвертая&#039;&#039;&#039; группа вершин соответствует вычислению весов кластеров &amp;lt;math&amp;gt;w_{j}&amp;lt;/math&amp;gt;. Число вершин: &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;. Аргументом этой операции является нормировочный коэффициент &amp;lt;math&amp;gt;n_j&amp;lt;/math&amp;gt;. Результат срабатывания операции является выходным данным алгоритма.&lt;br /&gt;
&lt;br /&gt;
Описанный граф представлен на рис.4 и рис.5. Здесь вершины одной группы расположены в одной строке. Вершины-операции обозначены синим цветом, вершины-данные — оранжевым.&lt;br /&gt;
&lt;br /&gt;
[[Файл:M-step-Lavrushkin.png|thumb|1000px|center|Рисунок 4. Граф M-шага.]]&lt;br /&gt;
[[Файл:M-step2-Lavrushkin.png|thumb|600px|center|Рисунок 5. Граф M-шага с отображением входных и выходных данных.]]&lt;br /&gt;
&lt;br /&gt;
Графы вычисления математических ожиданий &amp;lt;math&amp;gt;\mu_j&amp;lt;/math&amp;gt; и ковариационных матриц &amp;lt;math&amp;gt;\Sigma_j&amp;lt;/math&amp;gt; представлены на рис. 6 и рис. 7.&lt;br /&gt;
&lt;br /&gt;
[[Файл:EM-alg-mean-Lavrushkin.png|thumb|1400px|center|Рисунок 6. Граф вычисления математического ожидания &amp;lt;math&amp;gt;\mu_j&amp;lt;/math&amp;gt;.]]&lt;br /&gt;
[[Файл:EM-alg-cov-Lavrushkin.png|thumb|1400px|center|Рисунок 7. Граф вычисления ковариационной матрицы &amp;lt;math&amp;gt;\Sigma_j&amp;lt;/math&amp;gt;.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
По графам из пункта 1.7 видно, что скрытые переменные &amp;lt;math&amp;gt;y_{ij}&amp;lt;/math&amp;gt; в E-шаге, &amp;lt;math&amp;gt;y_{ij}x_i&amp;lt;/math&amp;gt; в вычислении математических ожиданий &amp;lt;math&amp;gt;\mu_{j}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;y_{ij}(x_i - \mu_j)(x_i - \mu_j)&amp;lt;/math&amp;gt; в вычислении ковариационных матриц &amp;lt;math&amp;gt;\Sigma_{j}&amp;lt;/math&amp;gt; в M-шаге вычисляются независимо (&amp;lt;math&amp;gt;i = \overline{1, n}, \, j = \overline{1, k}&amp;lt;/math&amp;gt;). Таким образом, при условии наличия неограниченного числа процессоров эти операции можно распараллелить как по числу наблюдений, так и по числу кластеров. Однако в отсутствии неограниченного числа процессорв целесообразно проводить распараллеливание по числу наблюдений, потому что, как правило, число наблюдений значительно больше числа кластеров  (&amp;lt;math&amp;gt;n \gg q&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
При классификации по ширине ЯПФ его сложность будет &amp;lt;math&amp;gt;O(nk)&amp;lt;/math&amp;gt;. Сложность ЯПФ при классификации по высоте зависит от способа вычисления обратных матриц и определителей ковариационных матриц, а также от способа суммирования при вычислении скрытых переменных и обновлении вектора параметров. Предположим, что размерность элементов выборки &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; и число кластеров &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; значительно меньше числа элементов выборки &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; (&amp;lt;math&amp;gt;k \ll n, q \ll n&amp;lt;/math&amp;gt;). Тогда вычисление обратных матриц и определителей ковариационных матриц можно не учитывать. Пусть для вычисления сумм используется пирамида сдваиванием. Тогда сложность суммирования при вычислении скрытых переменных равна &amp;lt;math&amp;gt;O(\log{k})&amp;lt;/math&amp;gt;, а при обновлении вектора параметров — &amp;lt;math&amp;gt;O(\log{n})&amp;lt;/math&amp;gt;. Следовательно, при классификации по высоте ЯПФ его сложность будет &amp;lt;math&amp;gt;O(\log{nk})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; — число кластеров; &amp;lt;math&amp;gt;X =\{x_{1}, x_{2}, ..., x_{n}\}&amp;lt;/math&amp;gt; — множество из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; наблюдений &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt;-мерного пространства.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем входных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;nq + 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: &amp;lt;math&amp;gt;(w, \theta) = (w_1, ..., w_k; \mu_1, ..., \mu_k; \Sigma_1, ..., \Sigma_k)&amp;lt;/math&amp;gt; — параметры смеси гауссовых распределений; &amp;lt;math&amp;gt;Y&amp;lt;/math&amp;gt; — матрица размера &amp;lt;math&amp;gt;n \times k&amp;lt;/math&amp;gt; с вероятностями членства в кластерах.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;k(n + q^2 + q + 1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
Алгоритм является &#039;&#039;недетерминированным&#039;&#039;. Число итераций до сходимости метода зависит от начального приближения и выбранного критерия останова.&lt;br /&gt;
&lt;br /&gt;
Предположим, что размерность элементов выборки &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; и число кластеров &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; значительно меньше числа элементов выборки &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; (&amp;lt;math&amp;gt;k \ll n, q \ll n&amp;lt;/math&amp;gt;), а число итераций до сходимости метода равно &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;. Тогда вычислительная мощность алгоритма, как отношение числа операций к суммарному объему входных и выходных данных, имеет порядок &amp;lt;math&amp;gt;O\bigg(\frac{kq^2}{q + k}m\bigg)&amp;lt;/math&amp;gt;.&lt;br /&gt;
==== Достоинства и недостатки алгоритма ====&lt;br /&gt;
Среди достоинств EM-алгоритма можно выделить следующие:&lt;br /&gt;
* Мощная статистическая основа.&lt;br /&gt;
* Линейное увеличение сложности при росте объема данных.&lt;br /&gt;
* Устойчивость к шумам и пропускам в данных.&lt;br /&gt;
* Возможность построения желаемого числа кластеров.&lt;br /&gt;
* Быстрая сходимость при удачной инициализации.&lt;br /&gt;
К недостаткам EM-алгоритма можно отнести следующее:&lt;br /&gt;
* Алгоритм неустойчив по начальным данным (то есть тем, которые инициализируют вектор параметров на первой итерации), так как он находит локальный экстремум, значение которого может оказаться гораздо ниже, чем глобальный максимум. В зависимости от выбора начального приближения алгоритм может сходиться к разным точкам. Также может сильно варьироваться скорость сходимости.&lt;br /&gt;
* Алгоритм не позволяет определять количество &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; компонент смеси. Эта величина является структурным параметром алгоритма.&lt;br /&gt;
* Предположение о нормальности всех измерений данных не всегда выполняется.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
&lt;br /&gt;
Для исследования масштабируемости EM-алгоритм кластеризации был реализован с помощью технологии MPI. Была реализована версия алгоритма с диагональными матрицами ковариации. В качестве критерия останова было выбрано достижение максимального числа итераций (соответственно, вычисление логарифмического правдоподобия на каждой итерации не проводится).&lt;br /&gt;
&lt;br /&gt;
Алгоритм параллельной реализации:&lt;br /&gt;
# Распределение элементов выборки. Процесс 0 распределяет поровну элементы выборки по остальным процессам.&lt;br /&gt;
# Инициализация параметров смеси гауссовых распределений. Процесс 0 инициализирует параметры и отправляет их остальным процессам. &amp;lt;math&amp;gt;\mu_j&amp;lt;/math&amp;gt; инициализируются случайными значениями в отрезке  &amp;lt;math&amp;gt;[-1, 1]&amp;lt;/math&amp;gt;, ковариационные матрицы &amp;lt;math&amp;gt;\Sigma_j&amp;lt;/math&amp;gt; определяются как единичные, веса &amp;lt;math&amp;gt;w_i&amp;lt;/math&amp;gt; кластеров задаются равными &amp;lt;math&amp;gt;\frac{1}{k}&amp;lt;/math&amp;gt;.&lt;br /&gt;
# Выполнение E-шага и M-шага алгоритма до достижения максимального числа итераций.&lt;br /&gt;
## E-шаг. Каждый процесс вычисляет значения скрытых переменных &amp;lt;math&amp;gt;y_{ij}&amp;lt;/math&amp;gt; по своему набору элементов выборки.&lt;br /&gt;
## M-шаг. &lt;br /&gt;
### Каждый процесс вычисляет суммы значений скрытых переменных &amp;lt;math&amp;gt;\sum_{i = 1}^{n\_proc_i}y_{ij}&amp;lt;/math&amp;gt; для каждого кластера &amp;lt;math&amp;gt;j = \overline{1, k}&amp;lt;/math&amp;gt; по своему набору элементов выборки и отправляет полученные суммы процессу 0. Процесс 0 вычисляет значения &amp;lt;math&amp;gt;n_j&amp;lt;/math&amp;gt; по полученным суммам и отправляет их остальным процессам. Каждый процесс обновляет значения &amp;lt;math&amp;gt;w_j&amp;lt;/math&amp;gt; по полученным значениям &amp;lt;math&amp;gt;n_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
### Каждый процесс вычисляет суммы &amp;lt;math&amp;gt;\sum_{i = 1}^{n\_proc_i}y_{ij}x_i&amp;lt;/math&amp;gt; для каждого кластера &amp;lt;math&amp;gt;j = \overline{1, k}&amp;lt;/math&amp;gt; по своему набору элементов выборки и отправляет полученные суммы процессу 0. Процесс 0 вычисляет суммы &amp;lt;math&amp;gt;\sum_{i = 1}^{n}y_{ij}x_i&amp;lt;/math&amp;gt; для каждого кластера &amp;lt;math&amp;gt;j = \overline{1, k}&amp;lt;/math&amp;gt; по всем элементам выборки и отправляет их остальным процессам. С помощью полученных сумм каждый процесс вычисляет значения математических ожиданий &amp;lt;math&amp;gt;\mu_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
### Каждый процесс вычисляет суммы &amp;lt;math&amp;gt;sum_l = \sum_{i = 1}^{n\_proc_i}y_{ij}(x_{il} - \mu_{jl}^{new})^2 \, (l = \overline{1, q})&amp;lt;/math&amp;gt; для каждого кластера &amp;lt;math&amp;gt;j = \overline{1, k}&amp;lt;/math&amp;gt; по своему набору элементов выборки и отправляет полученные суммы процессу 0. Процесс 0 вычисляет суммы &amp;lt;math&amp;gt;sum_l = \sum_{i = 1}^{n}y_{ij}(x_{il} - \mu_{jl}^{new})^2 \, (l = \overline{1, q})&amp;lt;/math&amp;gt; для каждого кластера &amp;lt;math&amp;gt;j = \overline{1, k}&amp;lt;/math&amp;gt; по всем элементам выборки и отправляет их остальным процессам. С помощью полученных сумм каждый процесс вычисляет значения диагональных элементов матриц ковариации &amp;lt;math&amp;gt;\Sigma_j&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Распараллеливание было проведено по числу элементов выборки, поэтому и исследование масштабируемости было проведено для числа элементов выборки. Исследование проводилось на суперкомпьютере &amp;quot;Ломоносов&amp;quot;&amp;lt;ref name=&amp;quot;Lom&amp;quot;&amp;gt;Воеводин Вл., Жуматий С., Соболев С., Антонов А., Брызгалов П., Никитенко Д., Стефанов К., Воеводин Вад. Практика суперкомпьютера «Ломоносов» // Открытые системы, 2012, N 7, С. 36-39.&amp;lt;/ref&amp;gt; [http://parallel.ru/cluster Суперкомпьютерного комплекса Московского университета].&lt;br /&gt;
&lt;br /&gt;
Набор и границы значений изменяемых параметров запуска реализации алгоритма: &lt;br /&gt;
* число процессов [8 : 128] с шагом 8;&lt;br /&gt;
* число элементов выборки [1000000 : 20000000] с шагом 1000000;&lt;br /&gt;
* размерность элементов выборки 4;&lt;br /&gt;
* число кластеров 4;&lt;br /&gt;
* число итераций 50.&lt;br /&gt;
&lt;br /&gt;
Для каждого набора параметров измерялось среднее время выполнения одной итерации алгоритма. На следующем рисунке приведен график производительности данной реализации EM-алгоритма кластеризации в зависимости от изменяемых параметров запуска.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Em-performance-Lavrushkin.png|thumb|1650px|center|Рисунок 8. Параллельная реализация EM-алгоритма кластеризации. Изменение производительности в зависимости от числа процессов и числа элементов выборки.]]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/HighVoltageRocknRoll/EM-clusterization_scalability Исследованная параллельная MPI-реализация на языке C]&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
# [http://docs.opencv.org/2.4/modules/ml/doc/expectation_maximization.html OpenCV];&lt;br /&gt;
# [http://arma.sourceforge.net/docs.html#gmm_diag Armadillo] — OpenMP реализация с предположением диагональности ковариационных матриц;&lt;br /&gt;
# [http://www.mlpack.org/docs/mlpack-git/doxygen.php?doc=classmlpack_1_1gmm_1_1GMM.html MLPack];&lt;br /&gt;
# [http://scikit-learn.org/stable/modules/mixture.html scikit-learn];&lt;br /&gt;
# [http://www.mathworks.com/help/stats/clustering-using-gaussian-mixture-models.html Matlab];&lt;br /&gt;
# [https://github.com/Corv/CUDA-GMM-MultiGPU CUDA реализация №1];&lt;br /&gt;
# [http://andrewharp.com/gmmcuda CUDA реализация №2].&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;/div&gt;</summary>
		<author><name>Algoman</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:Sergey_Lavrushkin&amp;diff=17685</id>
		<title>Обсуждение участника:Sergey Lavrushkin</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:Sergey_Lavrushkin&amp;diff=17685"/>
		<updated>2016-11-16T13:04:46Z</updated>

		<summary type="html">&lt;p&gt;Algoman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Замечания к [[Участник:Sergey_Lavrushkin/EM-алгоритм_кластеризации]] ==&lt;br /&gt;
&lt;br /&gt;
1) отсутствует оценка ширины ЯПФ параллельного алгоритма во врезке в начале статьи&lt;br /&gt;
&lt;br /&gt;
2) отсутствует оценка вычислительной мощности алгоритма в п 1.10 &lt;br /&gt;
&lt;br /&gt;
3) пункты 2.1 и 2.2 должны быть 2.4 и 2.7, согласно формату описания [[Структура_описания_свойств_алгоритмов]]&lt;br /&gt;
&lt;br /&gt;
4) &#039;&#039;&#039;Далее - правки с нового этапа проверки.&#039;&#039;&#039; Проверьте орфографию. Обнаружил, например, загадочное слово &amp;quot;единчиные&amp;quot;&lt;br /&gt;
&lt;br /&gt;
5) Нет ссылок на источники из списка литературы&lt;br /&gt;
&lt;br /&gt;
6) В п 1.2 отдельно выделите, что такое параметр q - он участвует в оценках во врезке, нужно дать возможность читателю быстро найти, что это&lt;br /&gt;
&lt;br /&gt;
7) &amp;quot;В случае смести гауссовых распределений предполагается, что все компоненты имеют многомерное нормальное распределение&amp;quot; - гауссово распределение и есть нормальное. Лучше  использовать только &amp;quot;гауссово&amp;quot;, или только &amp;quot;нормальное&amp;quot;, чтоб людей не путать&lt;br /&gt;
&lt;br /&gt;
8)  &amp;quot;То есть в случае q-мерного пространства признаков...&amp;quot; - формулу для сигмы квадрат лучше перенести в соотв. пункт списка после слова &amp;quot;где&amp;quot;, а в скобках указать, что его еще называют расстоянием Махаланобиса&lt;br /&gt;
&lt;br /&gt;
== Замечания к пункту 2.4 от 16.11.2016 == &lt;br /&gt;
&lt;br /&gt;
* какие выводы можно сделать о масштабируемости алгоритма, исходя из полученных данных? Требуется явно написать это в пункте.&lt;br /&gt;
* текст с особенностями паралелльной реализации лучше перенести в пункт 2.3&lt;/div&gt;</summary>
		<author><name>Algoman</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:MelLain/%D0%95%D0%9C-%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_(%D0%A2%D0%B5%D0%BC%D0%B0%D1%82%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B5_%D0%BC%D0%BE%D0%B4%D0%B5%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5)&amp;diff=17677</id>
		<title>Участник:MelLain/ЕМ-алгоритм (Тематическое моделирование)</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:MelLain/%D0%95%D0%9C-%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_(%D0%A2%D0%B5%D0%BC%D0%B0%D1%82%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B5_%D0%BC%D0%BE%D0%B4%D0%B5%D0%BB%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5)&amp;diff=17677"/>
		<updated>2016-11-16T12:57:50Z</updated>

		<summary type="html">&lt;p&gt;Algoman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Algoman}}&lt;br /&gt;
Статью подготовили:&lt;br /&gt;
&lt;br /&gt;
* [[U:MelLain|Мурат Апишев]] (реализация кода, описание теоретической части и деталей реализации);&lt;br /&gt;
* [[U:Заночкин Андрей|Андрей Заночкин]] (реализация кода, информационный граф, оценки сложности и экспериментальная часть).&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Тематическое моделирование&#039;&#039;&#039;&amp;lt;ref&amp;gt;https://ru.wikipedia.org/wiki/Тематическое_моделирование&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;http://www.machinelearning.ru/wiki/index.php?title=Тематическое_моделирование&amp;lt;/ref&amp;gt; - одно из направлений статистического анализа текстовых коллекций в машинном обучении. В литературе описываются многочисленные разновидности моделей, а также методов их обучения. В данной статье будет рассмотрена тематическая модель &#039;&#039;вероятностного латентного семантического анализа&#039;&#039;&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Probabilistic_latent_semantic_analysis&amp;lt;/ref&amp;gt; (PLSA), и процесс её обучения с помощью параллельного ЕМ-алгоритма.&lt;br /&gt;
&lt;br /&gt;
Существует множество разновидностей ЕМ-алгоритмов, ориентированных на учёт тех или иные аспектов решаемой задачи. Наиболее простым вариантом является т.н. &#039;&#039;оффлайновый&#039;&#039; алгоритм, непригодный для работы с большими текстовыми данными в силу значительных требований к потребляемой оперативной памяти. Существует ряд модернизаций этого алгоритма, позволяющих избавить его от ряда недостатков. Наилучшей из них является &#039;&#039;онлайновый&#039;&#039; вариант алгоритма. Тем не менее, в силу относительно высокой сложности его эффективной параллельной реализации, в данной статье будет рассматриваться гибридный вариант алгоритма, избавленный от большинства недостатков оффлайнового, но имеющий меньшую скорость сходимости, чем онлайновый.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание модели ===&lt;br /&gt;
&lt;br /&gt;
В большинстве тематических моделей коллекция текстов рассматривается в виде &amp;quot;мешка слов&amp;quot;, т.е. модель учитывает только статистическую встречаемость слов в документах и никак не использует информацию об их взаимном расположении внутри документа. &lt;br /&gt;
&lt;br /&gt;
Вероятностная модель PLSA имеет следующий вид:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
F \approx \Phi \times \Theta&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Здесь &amp;lt;math&amp;gt;F&amp;lt;/math&amp;gt; - это матрица исходных данных размера &amp;lt;math&amp;gt;|W| \times |D|&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; - это множество документов, а &amp;lt;math&amp;gt;W&amp;lt;/math&amp;gt; - словарь коллекции, т.е. множество всех уникальных слов, встретившихся в документах. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\Phi&amp;lt;/math&amp;gt; - это матрица параметров модели размера &amp;lt;math&amp;gt;|W| \times |T|&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - это множество тем, которые мы хотим извлечь из коллекции. Под темой в бытовом смысле смысле понимается набор слов, характеризующих её. Формально говоря, тема - это вероятностное распределение на множестве слов &amp;lt;math&amp;gt;W&amp;lt;/math&amp;gt;, поэтому матрица &amp;lt;math&amp;gt;\Phi&amp;lt;/math&amp;gt; является стохастической, т.е. столбцы её неотрицательны и суммируются в единицу.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\Theta&amp;lt;/math&amp;gt; - матрица результатов кластеризации обучающей коллекции по полученным темам размера &amp;lt;math&amp;gt;|T| \times |D|&amp;lt;/math&amp;gt;, в ней столбцы также являются вероятностными распределениями, на этот раз документов на множестве тем.&lt;br /&gt;
&lt;br /&gt;
Фактически, PLSA есть ни что иное, как задача приближённого стохастического матричного разложения, в ходе которой производится мягкая бикластеризация данных (мягкая - потому что объекты распределяются по классам не строго, а с некоторой вероятностью, би - потому что производится одновременная кластрезация слов по темам, и тем - по документам). Поставленную задачу можно решать методом максимального правдоподобия, с помощью ЕМ-алгоритма.&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;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\mathcal{L}(\Phi, \Theta) = \sum_{d \in D}\sum_{w \in d} n_{dw} \,\mathrm{ln}(\sum_{t \in T} \phi_{wt} \theta_{td}) \rightarrow \underset{\Phi, \Theta}{\mathrm{max}}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\sum_{w \in W} \phi_{wt} = 1, \, \forall t \in T, \quad \phi_{wt} \ge 0;&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\sum_{t \in T} \theta_{td} = 1, \, \forall d \in D, \quad \theta_{td} \ge 0.&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Прямая оптимизация логарифма правдоподобия - очень сложная задача, поэтому её решают приближённо с помощью метода простых итераций, в котором чередуются два шага: E (expectation) и M (maximization). Перед первой итерацией выбираются начальные приближения параметров &amp;lt;math&amp;gt;\Phi&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\Theta&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
На Е-шаге по текущим значениям параметров с помощью формулы Байеса вычисляются вспомогательные переменные - условные вероятности &amp;lt;math&amp;gt;p(t\, | \,d, \,w)&amp;lt;/math&amp;gt; для всех тем &amp;lt;math&amp;gt;t \in T&amp;lt;/math&amp;gt;, для каждого термина &amp;lt;math&amp;gt;w \in d&amp;lt;/math&amp;gt; для каждого документа &amp;lt;math&amp;gt;d \in D&amp;lt;/math&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
p(t\, | \,d, \,w ) = \cfrac{\phi_{wt}\theta_{td}}{\sum_{s \in T}\phi_{ws}\theta_{sd}}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На М-шаге, наоброт, по условным вероятностям &amp;lt;math&amp;gt;p(t\, | \,d, \,w)&amp;lt;/math&amp;gt; вычисляется новое приближение параметров &amp;lt;math&amp;gt;\phi_{wt}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\theta_{td}&amp;lt;/math&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\phi_{wt} = \cfrac{\hat n_{wt}}{\hat n_t}, \quad \hat n_t = \sum_{w \in W} \hat n_{wt}, \quad \hat n_{wt} = \sum_{d \in D} n_{dw} p(t\, | \,d, \,w )&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
\theta_{td} = \cfrac{\hat n_{dt}}{\hat n_d}, \quad \hat n_d = \sum_{t \in T} \hat n_{dt}, \quad \hat n_{dt} = \sum_{w \in d} n_{dw} p(t\, | \,d, \,w )&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Строгое обоснование данных формул можно получить с помощью теоремы Куна-Таккера.&lt;br /&gt;
&lt;br /&gt;
=== Общие слова о модернизациях ===&lt;br /&gt;
&lt;br /&gt;
Как уже было сказано, и как видно из описания выше, данный алгоритм сложно применять на практике в чистом виде из-за необходимости хранения трёхмерной матрицы &amp;lt;math&amp;gt;p(t\, | \,d, \,w)&amp;lt;/math&amp;gt; и  двумерной матрицы &amp;lt;math&amp;gt;\Theta&amp;lt;/math&amp;gt;, размеры которых зависят от количества обрабатываемых и данных, которых может быть очень много.&lt;br /&gt;
&lt;br /&gt;
Для борьбы с описанной проблемой можно производить вычисления более рационально, отказавшись от хранения обеих матриц и вычисляя необходимы значения на лету. При наличии обученной модели &amp;lt;math&amp;gt;\Phi&amp;lt;/math&amp;gt; получить векторы распределений &amp;lt;math&amp;gt;\theta_d&amp;lt;/math&amp;gt; (если в этом есть необходимость) можно, произведя одну итерацию алгоритма, в ходе которой сама модель обновляться не будет.&lt;br /&gt;
&lt;br /&gt;
В этом варианте алгоритма вычисление &amp;lt;math&amp;gt;\theta_d&amp;lt;/math&amp;gt; будет перенесено с М-шага на Е-шаг, и для каждого нового документа этот вектор будет инициализирован равномерным распределением. Для ускорения скорости сходимости можно производить итерации &amp;quot;пересчёт &amp;lt;math&amp;gt;p(t\, | \,d, \,w)&amp;lt;/math&amp;gt;&amp;quot; - &amp;quot;обновление &amp;lt;math&amp;gt;\theta_d&amp;lt;/math&amp;gt;&amp;quot; многократно в течении обработки одного документа.&lt;br /&gt;
&lt;br /&gt;
В дальнейшем подобные итерации будем называть &amp;quot;внутренними&amp;quot;, полный же однократный проход по всей коллекции будем называть итерацией &amp;quot;внешней&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Наиболее вычислительно затратной операцией в данном алгоритме является Е-шаг, в ходе которого рассчитываются вспомогательные переменные и векторы &amp;lt;math&amp;gt;\theta_d&amp;lt;/math&amp;gt;. С введением внутренних итераций нагрузка на Е-шаг только увеличивается.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
В целом, высокоуровневое описание ЕМ-алгоритма состоит из самих Е-шага и М-шага, что можно видеть на нижеприведённом листинге.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Приведём здесь листинг описываемого алгоритма:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;...&amp;quot;&amp;gt;&lt;br /&gt;
1. Инициализировать phi_wt^0 для всех w из W, t из T;&lt;br /&gt;
&lt;br /&gt;
2. Внешняя итерация по коллекции i = 1 ... num_outer_iter:&lt;br /&gt;
&lt;br /&gt;
3.      n_wt^i := 0, n_t^i := 0 для всех w из W и t из T;&lt;br /&gt;
&lt;br /&gt;
4.      Цикл по документам d из D:&lt;br /&gt;
&lt;br /&gt;
5.          Инициализировать вектор theta_d^0 для всех t из T и Z_w^0, для всех w из d;&lt;br /&gt;
&lt;br /&gt;
6.          Внутренняя итерация по документу j = 1 ... num_inner_iter:&lt;br /&gt;
&lt;br /&gt;
7.              Z_w^j := сумме по всем t из T (phi_wt^(i-1) * theta_td^(j-1)), для всех w из d;&lt;br /&gt;
&lt;br /&gt;
8.              theta_td^j := (1 / n_d) * на сумму по всем w из d (n_dw * phi_wt^(i-1) * theta_td^(j-1) / Z_w^j), для всех t из T;&lt;br /&gt;
&lt;br /&gt;
9.          Увеличить n_wt^i и n_t^i на (n_dw * phi_wt^(i-1) * theta_td / Z_w), для всех w из W и t из T;&lt;br /&gt;
&lt;br /&gt;
10.      phi_wt^i := (n_wt^i / n_t^i),  для всех w из W и t из T&lt;br /&gt;
&lt;br /&gt;
Здесь Z_w - это сумма всех p(t| d, w) для данного документа, нормировочная константа.&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;num\_outer\_iter&amp;lt;/math&amp;gt; внешними итерациями и &amp;lt;math&amp;gt;num\_inner\_iter&amp;lt;/math&amp;gt; внутренними применительно к набору документов &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; и слов &amp;lt;math&amp;gt;W&amp;lt;/math&amp;gt;, классифицирующий коллекцию по темам &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Так на каждой внутренней итерации производится&lt;br /&gt;
&lt;br /&gt;
* умножений: &amp;lt;math&amp;gt;|W|\cdot|T| + 2|T|\cdot|D|&amp;lt;/math&amp;gt; ,&lt;br /&gt;
* делений : &amp;lt;math&amp;gt;|T|\cdot(|D| + 1)&amp;lt;/math&amp;gt;,&lt;br /&gt;
* сложений: &amp;lt;math&amp;gt;|W|\cdot(|T|-1) + |T|\cdot(|D| - 1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
А значит на одной внешней итерации производится&lt;br /&gt;
&lt;br /&gt;
* умножений: &amp;lt;math&amp;gt;(|W|\cdot|T| + 2|T|\cdot|D|)\cdot num\_inner\_iter \cdot |D|&amp;lt;/math&amp;gt; ,&lt;br /&gt;
* делений : &amp;lt;math&amp;gt;|T|\cdot(|D| + 1)\cdot num\_inner\_iter \cdot |D| + |W|\cdot|T|&amp;lt;/math&amp;gt; ,&lt;br /&gt;
* сложений: &amp;lt;math&amp;gt;\Big(\big[|W|\cdot(|T|-1) + |T|\cdot(|D| - 1)\big]\cdot num\_inner\_iter + |W|\cdot|T|\Big)\cdot |D|&amp;lt;/math&amp;gt; .&lt;br /&gt;
&lt;br /&gt;
Соответственно для всего алгоритма каждая из этих операций повторяется &amp;lt;math&amp;gt;num\_outer\_iter&amp;lt;/math&amp;gt; раз. Наиболее часто выполняется операция умножения, однако порядок величин одинаковый. Разница будет заметна лишь в том случае, когда &amp;lt;math&amp;gt;|D|&amp;lt;/math&amp;gt; имеет меньший порядок, чем &amp;lt;math&amp;gt;|W|&amp;lt;/math&amp;gt;. В этом случае делений будет значительно меньше, чем сложений и умножений. &lt;br /&gt;
&lt;br /&gt;
По классификации по последовательной сложности ЕМ-алгоритм можно отнести к &#039;&#039;линейным&#039;&#039; по &amp;lt;math&amp;gt;num\_inner\_iter, num\_outer\_iter , |T|, |W|&amp;lt;/math&amp;gt;, а попеременной &amp;lt;math&amp;gt;|D|&amp;lt;/math&amp;gt; - &#039;&#039;с квадратичной сложностью&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
Опишем [[глоссарий#Граф алгоритма|граф алгоритма]]&amp;lt;ref&amp;gt;Воеводин В.В.  Математические основы параллельных вычислений// М.: Изд. Моск. ун-та, 1991. 345 с.&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Воеводин В.В., Воеводин Вл.В. Параллельные вычисления. – СПб.: БХВ - Петербург, 2002. – 608 с.&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;Фролов А.В.. Принципы построения и описание языка Сигма. Препринт ОВМ АН N 236. М.: ОВМ АН СССР, 1989.&amp;lt;/ref&amp;gt; как аналитически, так и в виде рисунка. &lt;br /&gt;
&lt;br /&gt;
[[Файл:EM-temat inner1.png|thumb|left|200px|Рисунок 1. Граф алгоритма внутренней итерации. Рассмотрено две итерации цикла.]]&lt;br /&gt;
&#039;&#039;&#039;Первый&#039;&#039;&#039; граф описывает алгоритм внутреннего цикла. &lt;br /&gt;
[[Файл:EM-temat doc.png|thumb|right|400px|Рисунок 2. Граф алгоритма анализа документа]]&lt;br /&gt;
[[Файл:EM-temat outer.png|thumb|right|400px|Рисунок 3. Граф алгоритма внешней итерации. Рассмотрен случай трех внешних итераций, при трех рассматриваемых документах]]&lt;br /&gt;
&lt;br /&gt;
В качестве входных параметров выступают &lt;br /&gt;
* вектор &amp;lt;math&amp;gt;\theta_{init} &amp;lt;/math&amp;gt;, инициализированный значениями &amp;lt;math&amp;gt;1/|T|&amp;lt;/math&amp;gt;, длиной &amp;lt;math&amp;gt;|T|&amp;lt;/math&amp;gt;,&lt;br /&gt;
* матрица &amp;lt;math&amp;gt;\Phi&amp;lt;/math&amp;gt;, размера &amp;lt;math&amp;gt;|W|\times |T|&amp;lt;/math&amp;gt;,&lt;br /&gt;
* вектор &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, длины &amp;lt;math&amp;gt;|W|&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве выходных параметров выступают &lt;br /&gt;
* вектор &amp;lt;math&amp;gt;\theta&amp;lt;/math&amp;gt;, длиной &amp;lt;math&amp;gt;|T|&amp;lt;/math&amp;gt;,&lt;br /&gt;
* вектор &amp;lt;math&amp;gt;nZ&amp;lt;/math&amp;gt;, длиной &amp;lt;math&amp;gt;|W|&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Внутри алгоритма используются элементарные операции&lt;br /&gt;
* Умножения матрицы на вектор &amp;lt;math&amp;gt;M \cdot V&amp;lt;/math&amp;gt;,&lt;br /&gt;
* Поэлементного умножения вектора на вектор &amp;lt;math&amp;gt;V. \cdot V&amp;lt;/math&amp;gt;,&lt;br /&gt;
* Поэлементного деления вектора на вектор &amp;lt;math&amp;gt;U. \cdot V&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Данные операции были рассмотрены в [https://algowiki-project.org/ru/%D0%A1%D1%83%D0%BC%D0%BC%D0%B0_%D0%B2%D0%B5%D0%BA%D1%82%D0%BE%D1%80%D0%B0_%D0%B8_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%B2%D0%B5%D0%B4%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D1%8B_%D0%BD%D0%B0_%D0%B4%D1%80%D1%83%D0%B3%D0%BE%D0%B9_%D0%B2%D0%B5%D0%BA%D1%82%D0%BE%D1%80,_%D0%B2%D0%B5%D1%89%D0%B5%D1%81%D1%82%D0%B2%D0%B5%D0%BD%D0%BD%D0%B0%D1%8F_%D0%B2%D0%B5%D1%80%D1%81%D0%B8%D1%8F,_%D0%BF%D0%BE%D1%81%D0%BB%D0%B5%D0%B4%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D1%8B%D0%B9_%D0%B2%D0%B0%D1%80%D0%B8%D0%B0%D0%BD%D1%82,_%D0%BF%D0%BB%D0%BE%D1%82%D0%BD%D0%B0%D1%8F_%D0%BC%D0%B0%D1%82%D1%80%D0%B8%D1%86%D0%B0 соответствующей статье], поэтому не будем останавливаться отдельно на каждой из них.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй&#039;&#039;&#039; граф описывает Е-шаг алгоритма при анализе отдельного документа. &lt;br /&gt;
&lt;br /&gt;
В качестве входных параметров выступают &lt;br /&gt;
* матрица &amp;lt;math&amp;gt;\Phi&amp;lt;/math&amp;gt;, размера &amp;lt;math&amp;gt;|W|\times |T|&amp;lt;/math&amp;gt;,&lt;br /&gt;
* вектор &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, длины &amp;lt;math&amp;gt;|W|&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;|W|\times |T|&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Внутри алгоритма используются элементарные операции&lt;br /&gt;
* Суммирования элементов вектора &amp;lt;math&amp;gt;\Sigma&amp;lt;/math&amp;gt;,&lt;br /&gt;
* Поэлементного деления вектора на скаляр &amp;lt;math&amp;gt;V / c&amp;lt;/math&amp;gt;,&lt;br /&gt;
* Поэлементного умножения вектора на скаляр &amp;lt;math&amp;gt;V \cdot c&amp;lt;/math&amp;gt;,&lt;br /&gt;
* Умножения строк матрицы на элементы вектора &amp;lt;math&amp;gt;M. \cdot V&amp;lt;/math&amp;gt;,&lt;br /&gt;
* Умножения столбцов матрицы на элементы вектора &amp;lt;math&amp;gt;V. \cdot M&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
А также используется операция &amp;lt;math&amp;gt;inner&amp;lt;/math&amp;gt;, описанная на предыдущем шаге.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Третий&#039;&#039;&#039; граф описывает алгоритм внешнего цикла. &lt;br /&gt;
&lt;br /&gt;
В качестве входных параметров выступают &lt;br /&gt;
* Нулевая матрица, размера &amp;lt;math&amp;gt;|W|\times |T|&amp;lt;/math&amp;gt;,&lt;br /&gt;
* матрица &amp;lt;math&amp;gt;\Phi_0&amp;lt;/math&amp;gt;, размера &amp;lt;math&amp;gt;|W|\times |T|&amp;lt;/math&amp;gt;,&lt;br /&gt;
* Набор векторов &amp;lt;math&amp;gt;n(d_i)&amp;lt;/math&amp;gt;, длины &amp;lt;math&amp;gt;|W|&amp;lt;/math&amp;gt;, являющихся столбцами матрицы &amp;lt;math&amp;gt;n_{wd}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В качестве выходных параметров выступают &lt;br /&gt;
* вектор &amp;lt;math&amp;gt;\theta_{num\_outer\_iter}&amp;lt;/math&amp;gt;, длиной &amp;lt;math&amp;gt;|T|&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Внутри алгоритма используются элементарные операции&lt;br /&gt;
* Суммы двух матриц ,&lt;br /&gt;
* Суммы элементов столбцов матрицы  &amp;lt;math&amp;gt;\Sigma M&amp;lt;/math&amp;gt;,&lt;br /&gt;
* Деления столбцов матрицы на элементы вектора &amp;lt;math&amp;gt;M./ V&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
А также используется операция &amp;lt;math&amp;gt;Doc&amp;lt;/math&amp;gt;, описанная на втором шаге.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Е-шаг представляет собой наиболее подходящее место в алгоритме для применения параллелизма. Во-первых, потому, что является наиболее ресурсоёмким этапом, во-вторых - потому что в нём производится итерирование по документам коллекции, при этом обработка каждого документа выполняется фактически независимо.&lt;br /&gt;
&lt;br /&gt;
Параллелить также можно и М-шаг, но в данной статье это не будет рассматриваться за ненадобностью. В практических реализациях это делается крайне редко.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Если рассматривать EM-алгоритм на прикладном уровне, то в качестве входных параметров выступает коллекция документов &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, которая предварительно анализируется и порождает множество слов &amp;lt;math&amp;gt;W&amp;lt;/math&amp;gt;. Также к входным данным относится количество тем &amp;lt;math&amp;gt;T&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;n_{dw}&amp;lt;/math&amp;gt;, отвечающая количеству слов &amp;lt;math&amp;gt;w&amp;lt;/math&amp;gt;, встречающихся в документе &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;. По определению элементы этой матрицы могут принимать лишь неотрицательные &#039;&#039;целые&#039;&#039; значения.&lt;br /&gt;
* пара параметров &amp;lt;math&amp;gt;num\_outer\_iter, num\_inner\_iter&amp;lt;/math&amp;gt; и количество тем &amp;lt;math&amp;gt;|T|&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;|W|\times |D|&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;\Phi&amp;lt;/math&amp;gt;, то есть распределений слов в полученных темах (если добавить кэширование матрицы &amp;lt;math&amp;gt;\Theta&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;|W|\times|T|  \big(+ |T|\times|D| \big)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
С вычислительной точки зрения алгоритм является детерминированным, в силу фиксированного взаимного размещения данных в памяти. Масштабируемость параллельной реализации может зависеть от ряда факторов, которые будут рассмотрены далее.&lt;br /&gt;
&lt;br /&gt;
С точки зрения результата работы алгоритм детерминированным не является, он неустойчив, имеет тенденцию к попаданию в локальные минимумы. Результат работы сильно зависит от начального приближения, которое, как правило, выбирается случайным образом.&lt;br /&gt;
&lt;br /&gt;
Вычислительная мощность алгоритма равна отношению числа операций к суммарному объему входных и выходных данных. Она показывает, сколько операций приходится на единицу переданных данных. &lt;br /&gt;
&lt;br /&gt;
Суммарное количество входных параметров можно читать равным &amp;lt;math&amp;gt;|W|\times|D| &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Суммарное количество выходных параметров в точности равно &amp;lt;math&amp;gt;|W|\times|T| (+ |T|\times |D|) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Количество операций при больших значениях параметров &amp;lt;math&amp;gt;num\_outer\_iter&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;num\_inner\_iter&amp;lt;/math&amp;gt; можно считать равным&lt;br /&gt;
&amp;lt;math&amp;gt;(2|W|\cdot|T| + 4|T|\cdot|D|)\cdot |D| \cdot num\_inner\_iter \cdot num\_outer\_iter&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Итак вычислительная сложность алгоритма равна &lt;br /&gt;
&amp;lt;math&amp;gt;\frac{(2|W|\cdot|T| + 4|T|\cdot|D|)\cdot |D|}{|W|\cdot|D| + |W|\cdot|T| (+ |T|\cdot |D|)} \cdot num\_inner\_iter \cdot num\_outer\_iter&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Очевидно, что по параметрам итерации вычислительная сложность линейна. Более сложная зависимость наблюдается по параметрам количества тем, слов и документов. Наибольший интерес представляет зависимость сложности от количества документов, поскольку на практике именно этот параметр имеет больший порядок, нежели остальные значения. Так асимптотически алгоритм имеет линейную сложность по этому параметру. По остальным же параметрам вычислительная сложность ограничена некоторой константой, которая зависит от других параметров и может быть легко получена взятием предела выражения по соответствующим переменным.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
В простейшем варианте (без внутренних итераций по &amp;lt;math&amp;gt;\theta_d&amp;lt;/math&amp;gt; и с хранением всех этих векторов) алгоритм без применения параллелизма и векторизации на языке Python выглядит следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
# Author: Murat Apishev (great-mel@yandex.ru)&lt;br /&gt;
&lt;br /&gt;
def plsa_em(n_dw, num_topics, max_outer_iter, Phi_init, Theta_init):&lt;br /&gt;
    num_tokens, num_docs = n_dw.shape&lt;br /&gt;
    Phi = Phi_init if not Phi_init is None else init_matrix(num_tokens, num_topics)&lt;br /&gt;
    Theta = Theta_init if not Theta_init is None else init_matrix(num_topics, num_docs)&lt;br /&gt;
&lt;br /&gt;
    for i in xrange(max_outer_iter):&lt;br /&gt;
        time_start = time.time()&lt;br /&gt;
        n_wt = np.zeros([num_tokens, num_topics]);&lt;br /&gt;
        n_t = [0] * num_topics&lt;br /&gt;
        Theta_new = np.array(Theta)&lt;br /&gt;
&lt;br /&gt;
        for d in xrange(num_docs):&lt;br /&gt;
            Z_w = [0] * num_tokens&lt;br /&gt;
            for w in xrange(num_tokens):&lt;br /&gt;
                z_w = 0.0&lt;br /&gt;
                for t in xrange(num_topics):&lt;br /&gt;
                    z_w += Phi[w, t] * Theta[t, d]&lt;br /&gt;
                Z_w[w] = z_w&lt;br /&gt;
&lt;br /&gt;
            for t in xrange(num_topics):&lt;br /&gt;
                value = 0.0&lt;br /&gt;
                for w in xrange(num_tokens):&lt;br /&gt;
                    if Z_w[w] &amp;lt; EPS:&lt;br /&gt;
                        continue&lt;br /&gt;
&lt;br /&gt;
                    value += n_dw[w, d] * Phi[w, t] * Theta[t, d] / Z_w[w]&lt;br /&gt;
&lt;br /&gt;
                denominator = np.sum(n_dw[:, d])&lt;br /&gt;
                if denominator &amp;lt; EPS:&lt;br /&gt;
                    continue&lt;br /&gt;
&lt;br /&gt;
                Theta_new[t, d] = 1.0 / np.sum(n_dw[:, d]) * value&lt;br /&gt;
&lt;br /&gt;
            for w in xrange(num_tokens):&lt;br /&gt;
                for t in xrange(num_topics):&lt;br /&gt;
                    if Z_w[w] &amp;lt; EPS:&lt;br /&gt;
                        continue&lt;br /&gt;
&lt;br /&gt;
                    value = n_dw[w, d] * Phi[w, t] * Theta[t, d] / Z_w[w]&lt;br /&gt;
                    n_wt[w, t] += value&lt;br /&gt;
                    n_t[t] += value&lt;br /&gt;
&lt;br /&gt;
        Phi = n_wt / n_t&lt;br /&gt;
        Theta = Theta_new&lt;br /&gt;
    return Phi, Theta&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;n_{wt}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\Phi&amp;lt;/math&amp;gt;. Они хранятся в виде хэш-таблиц, где ключом является слово, а значением - вектор, длинной в число тем. В силу последовательного хранения данных вектором, производится эффективное итерирование в циклах по темам.&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вне зависимости от того, каким образом производить параллельную/распределённую обработку коллекции, основным способом увеличения производительности является разделение обработки отдельных документов. Существующие архитектуры алгоритмов тематического моделирования (не только на основе описанного ЕМ-алгоритма) на MPI, Hadoop MapReduce, Spark, а также параллельные архитектуры на одиночных машинах, работают в рамках одной этой парадигмы.&lt;br /&gt;
&lt;br /&gt;
Как уже было отмечено, в описанном алгоритме большая часть вычислений приходится на Е-шаг (в некоторых экспериментах он занимал более 99% времени работы). Поэтому именно он был выбран в качестве объекта для реализации параллелизма. Общую схему можно описать следующим образом. Вместо того, чтобы обрабатывать документы в цикле последовательно, можно делать это параллельно, поскольку для описанного алгоритма обработка разных документов являются независимыми операциями. Таким образом, входные данные, то есть документы, разбиваются на пакеты, в каждом из которых находится фиксированное количество документов, каждый пакет сохраняется на диск в виде отдельного файла, все файлы хранятся в одной директории, подаваемой на вход алгоритму.&lt;br /&gt;
&lt;br /&gt;
Далее алгоритм перед началом очередной итерации прохода по коллекции просматривает рабочую директорию и сохраняет в специальную очередь имена файлов с документами. Перед началом каждой итерации производится создание нескольких параллельных потоков-обработчиков, каждый из которых занимается вычислением Е-шага. Для этого каждый обработчик, не занятый в текущий момент времени, проверяет очередь с именами файлов на наличие в ней необработанных пакетов, и, в случае присутствия таких, извлекает очередное имя файла, открывает сам файл и последовательно обрабатывает все находящиеся в нём документы. Имя обрабатываемого файла из очереди удаляется. Итерация заканчивается тогда, когда все обработчики завершили свою работу. На этом параллельный Е-шаг завершается, алгоритм производит последовательный М-шаг, и либо завершается, либо начинает новую внешнюю итерацию.&lt;br /&gt;
&lt;br /&gt;
Ключевым моментом организации распараллеливания в среде с разделяемой памятью (а здесь она именно такая) является организация доступа различных потоков к разделяемым ресурсам. В силу ручной реализации потоков (без использования OpenMP) решение проблемы ложится на авторов кода. Как было отмечено выше, разделяемыми ресурсами являются две матрицы размера &amp;quot;число слов&amp;quot; на &amp;quot;число тем&amp;quot;. Обе они имеют фиксированные размеры всё время работы алгоритма. Как было сказано, обе матрицы реализованы в виде хэш-таблиц с ключами-словами. Единицей блокировки является вектор, соответствующий одному слову. Для организации такого доступа каждая матрица хранит вектор объектов mutex, по одному на каждый ключ матрицы, и имеет методы, регулирующие, с помощью этих mutex-ов, доступ к каждой строке.&lt;br /&gt;
&lt;br /&gt;
Очередь имён файлов также имеет mutex, поскольку используется всеми потоками.&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
Данная параллельная реализация тестировалась на компьютере со вычислительными следующими характеристиками:&lt;br /&gt;
&lt;br /&gt;
Intel(R) Core(TM) i7-5820K @ 3.30GHz (6 физических ядер, 12 потоков, без использования аппаратного ускорения ядер).&lt;br /&gt;
&lt;br /&gt;
Соответственно, максимальное количество параллельных обработчиков было равно 12. В качестве входных данных использовалась коллекция писем [https://www.kaggle.com/kaggle/hillary-clinton-emails/downloads/hillary-clinton-emails-release-2015-09-11-01-39-01.zip Х. Клинтон] (точнее, её подмножество из 6000 тысяч писем, т. е. больше 80%). Вся коллекция, как было отмечено выше, делится на текстовые файлы, в каждом файле одна строка соответствует одному документу. Единицей параллелизма является файл.&lt;br /&gt;
&lt;br /&gt;
Измеряемыми параметрами масштабируемости являются:&lt;br /&gt;
&lt;br /&gt;
* количество тем;&lt;br /&gt;
* количество внутренних итераций;&lt;br /&gt;
* количество потоков-обработчиков.&lt;br /&gt;
&lt;br /&gt;
Количество документов в каждом пакете зафиксируем равным 100. Число внешних итераций - 10.&lt;br /&gt;
&lt;br /&gt;
Измеряемым параметром является время работы алгоритма без учёта вспомогательных операций (сбор словаря коллекции, который реализация умеет производить однократно и далее переиспользовать сохранённый на диск результат). Для каждого фиксированного числа тем и количества внутренних итераций построен двумерный график зависимости времени работы от числа потоков, т.е. график масштабируемости алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[file:PlsaEm.png|thumb|center|900px|Рисунок 4. Масштабируемость ЕМ-алгоритма для тематического моделирования. Столбцы соответствуют различному числу тем (слева направо 10, 20 и 40). Строки - числу внутренних итераций (сверху вниз 1, 5 и 10). Синие линии соответствуют времени работы алгоритма при различных значениях количества потоков (ось Х каждого графика), красные - идеальному масштабированию.]]&lt;br /&gt;
&lt;br /&gt;
Можно заметить, что качество параллелизма постоянно растёт с увеличением нагрузки на Е-шаг, что является признаком качественной архитектуры. Вывод сделан потому, что и увеличение объёма обрабатываемых данных, и ускорение скорости сходимости модели, и увеличение числа тем - всё это является основными источниками увеличения вычислительных затрат при работе алгоритма. Получается, что алгоритм при усложнении обрабатываемой задачи показывает всё более хорошую масштабируемость. В качестве примера рассматриватся в разы усложнённая задача: 200 тем и 20 внутренних итераций на той же коллекции текстов:&lt;br /&gt;
&lt;br /&gt;
[[file:PlsaEmHard.png|thumb|center|500px|Рисунок 5. Масштабируемость ЕМ-алгоритма для тематического моделирования в сложном случае. Обозначения аналогичны рис 4.]]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/MelLain/study/tree/master/C%2B%2B/Parallel-EM Реализация алгоритма на языке C++ (STL, Boost)]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Наиболее близкой (хотя далеко не идентичной) реализацией описанного алгоритма является ЕМ-алгоритм для тематического моделирования из библиотеки [http://www.bigartm.org BigARTM]. Там реализован полноценный онлайновый ЕМ-алгоритм с относительно сложной архитектурой распараллеливания, позволяющий добиться эффективной онлайновой обработки огромных текстовых коллекций на одной машине.&lt;br /&gt;
&lt;br /&gt;
Существуют и другие программные реализации алгоритмов для тематического моделирования, но большинство из них не использует ЕМ-алгоритм, или же использует его вариационный вариант, который здесь не рассматривается (хотя идеи параллелизма там используются схожие).&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Категория:Незаконченные статьи]]&lt;br /&gt;
[[Категория:ЕМ-алгоритм]]&lt;/div&gt;</summary>
		<author><name>Algoman</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%9C%D0%B0%D1%80%D0%B8%D1%8F_%D0%93%D0%BE%D1%82%D0%BC%D0%B0%D0%BD/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8,_%D0%BE%D1%81%D0%BD%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9_%D0%BD%D0%B0_%D0%BC%D0%B0%D0%BA%D1%81%D0%B8%D0%BC%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BE%D0%B6%D0%B8%D0%B4%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=17601</id>
		<title>Участник:Мария Готман/Алгоритм кластеризации, основанный на максимизации ожидания</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D0%B0%D1%80%D0%B8%D1%8F_%D0%93%D0%BE%D1%82%D0%BC%D0%B0%D0%BD/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8,_%D0%BE%D1%81%D0%BD%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9_%D0%BD%D0%B0_%D0%BC%D0%B0%D0%BA%D1%81%D0%B8%D0%BC%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BE%D0%B6%D0%B8%D0%B4%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=17601"/>
		<updated>2016-11-16T11:24:17Z</updated>

		<summary type="html">&lt;p&gt;Algoman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Авторы описания: [[Участник:Мария_Готман|Готман М.Л.]], [[Участник:Julia_lukashkina|Лукашкина Ю.Н.]]&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Задача кластеризации — это задача разбиения заданной входной выборки объектов на непересекающиеся подмножества, называемые кластерами, так, чтобы каждый кластер состоял из схожих объектов, а объекты разных кластеров существенно отличались. &lt;br /&gt;
&lt;br /&gt;
Для решения этой задачи можно использовать, например, метод максимизации ожидания, также известный как EM-алгоритм (англ. expectation-maximization) &amp;lt;ref&amp;gt;Воронцов К.В.; Математические методы обучения по прецедентам (теория обучения машин)&amp;lt;/ref&amp;gt;. В таком случае делается предположение, что входные данные — смесь многомерных нормальных распределений, соотвественно отдельный кластер — это одна компонента смеси. Предполагается, что количество кластеров является входным параметром алгоритма (существуют модификации EM-алгоритма, которые автоматически находят число кластеров, но они не рассматриваются в данной статье). Результат работы EM-алгоритма — веса кластеров и найденные параметры нормальных распределений для каждого кластера: вектора математических ожиданий и матрицы ковариации. &lt;br /&gt;
&lt;br /&gt;
Алгоритм EM кластеризации основан на итеративном выполнении двух последовательных шагов: E-шага и M-шага. На E-шаге вычисляются вспомогательные (скрытые) переменные, которые характеризуют апостериорную вероятность того, что определенный обучающий объект получен из фиксированной компоненты смеси. На M-шаге с помощью вычисленных скрытых переменных производится обновление параметров смеси: по определённым формулам пересчитываются веса кластеров, их математические ожидания и матрицы ковариаций.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что на работу EM-алгоритма значительно влияет начальное приближение его параметров. При неудачной инициализации алгоритм может не сойтись или сойтись в локальный экстремум.&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается частный случай EM-алгоритма, который работает с двумерными входными данными.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Em clusters 4.png|400px|thumb|center|Пример работы EM-алгоритма для 5ти кластеров.]]&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассматривается смесь многомерных нормальных распределений &amp;lt;math&amp;gt;p_j(x) = N(x;\mu_j, \Sigma_j) = \frac1{(2\pi)^{d/2}\sqrt{|\Sigma_j|}} \exp \biggl(-\frac{1}{2}(x - \mu_j) \Sigma_j^{-1} (x - \mu_j)^T\biggr) &amp;lt;/math&amp;gt; с весами &amp;lt;math&amp;gt;w_j&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;p(x)=\sum_{j=1}^kw_jp_j(x), \sum_{j=1}^kw_j =1, w_j \ge 0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
На вход алгоритму подаются &amp;lt;math&amp;gt;m &amp;lt;/math&amp;gt; объектов, каждый из которых имеет &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; признаков, в виде матрицы объектов-признаков &amp;lt;math&amp;gt;X \in \R^{m \times d}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; — количество кластеров.&lt;br /&gt;
&lt;br /&gt;
Алгоритм кластеризации, основанный на максимизации правдоподобия, итеративно выполняет два шага: E-шаг и M-шаг.&lt;br /&gt;
Идея алгоритма заключается в введении матрицы скрытых переменных &amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;g_{ij} \equiv P(\theta_j |x_i)&amp;lt;/math&amp;gt; обозначает вероятность принадлежности &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го объекта &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-му кластеру.&lt;br /&gt;
&lt;br /&gt;
На Е-шаге вычисляется ожидаемое значение скрытых переменных, на М-шаге выполняется максимизация логарифма полного правдоподобия, результатом которой являются новые значения параметров модели.&lt;br /&gt;
&lt;br /&gt;
На выходе получаем набор параметров модели для каждого кластера &amp;lt;math&amp;gt;\Theta = (w_1,...,w_k;\;\mu_1,...,\mu_k;\;\Sigma_1,...,\Sigma_k)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;w_j&amp;lt;/math&amp;gt; — вес &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-го кластера в смеси нормальных распределений, &amp;lt;math&amp;gt;\mu_j&amp;lt;/math&amp;gt; — математическое ожидание &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-ой компоненты смеси, &amp;lt;math&amp;gt;\Sigma_j&amp;lt;/math&amp;gt; — матрица ковариации &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-ой компоненты смеси.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;E-шаг&amp;lt;/b&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
На E-шаге вычисляется значение скрытых переменных &amp;lt;math&amp;gt;g_{ij}&amp;lt;/math&amp;gt; по текущему приближению параметров &amp;lt;math&amp;gt;\Theta&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;g_{ij} = \frac{w_jp_j(x_i)}{\sum_{s=1}^k w_sp_s(x_i)}&amp;lt;/math&amp;gt;, что интерпретируется как вероятность принадлежности объекту &amp;lt;math&amp;gt;x_i&amp;lt;/math&amp;gt; к &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-ому кластеру.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;M-шаг&amp;lt;/b&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
Будем максимизировать логарифм полного правдоподобия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;Q(\Theta) = \ln\prod_{i=1}^mp(x_i) = \sum_{i=1}^m\ln\sum_{j=1}^kw_jp_j(x_i) \rightarrow \max_{\Theta}&amp;lt;/math&amp;gt;, при условии &amp;lt;math&amp;gt;\sum_{j=1}^kw_j=1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Решением оптимизационной задачи являются формулы для пересчета параметров:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;w_j = \frac1m\sum_{i=1}^m g_{ij}&amp;lt;/math&amp;gt;, &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\mu_j = \frac1{mw_j}\sum_{i=1}^m g_{ij}x_i&amp;lt;/math&amp;gt;, &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\Sigma_j = \frac1{mw_j}\sum_{i=1}^m g_{ij}(x_i - \mu_j)(x_i - \mu_j)^T,\; j = 1, \dots, k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро алгоритма представляет собой итерационное вычисление всех параметров модели, независимое по &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; объектам выборки &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt;.&lt;br /&gt;
На каждой итерации алгоритма на Е-шаге пересчитывается значение скрытых переменных, на M-шаге пересчет параметров модели с учетом скрытых переменных.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как записано в [[#Вычислительное ядро алгоритма|описании ядра алгоритма]], основную часть метода составляют вычисления элементов матрицы G на E шаге, и пересчет параметров &amp;lt;math&amp;gt;\Theta&amp;lt;/math&amp;gt; на M-шаге.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
# Инициализация параметров&lt;br /&gt;
# for iter = 1 : max_iterations&lt;br /&gt;
# [E-шаг]&lt;br /&gt;
## вычисление &amp;lt;math&amp;gt;\Sigma_j^{-1}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\frac1{(2\pi)^{d/2}\sqrt{|\Sigma_j|}}, j = 1 : k&amp;lt;/math&amp;gt;&lt;br /&gt;
## вычисление &amp;lt;math&amp;gt;g_{ij},\;i = 1 : m, \; j = 1 : k&amp;lt;/math&amp;gt;&lt;br /&gt;
## вычисление &amp;lt;math&amp;gt;LL_i&amp;lt;/math&amp;gt; (логарифм правдоподобия), &amp;lt;math&amp;gt;\;i = 1 : m&amp;lt;/math&amp;gt;&lt;br /&gt;
# [M-шаг]&lt;br /&gt;
## вычисление &amp;lt;math&amp;gt;\tilde w_j = \sum_{i=1}^m g_{ij}, \; j = 1 : m&amp;lt;/math&amp;gt;&lt;br /&gt;
## вычисление &amp;lt;math&amp;gt;\tilde \mu_j = \sum_{i=1}^m g_{ij}x_i,\; j = 1 : k&amp;lt;/math&amp;gt;&lt;br /&gt;
## вычисление &amp;lt;math&amp;gt;\tilde \Sigma_j = \sum_{i=1}^m g_{ij}(x_i - \mu_j)^T(x_i - \mu_j),\; j = 1 : k&amp;lt;/math&amp;gt;&lt;br /&gt;
## нормировка &amp;lt;math&amp;gt;w_j = \frac{\tilde w_j}{m}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\mu_j = \frac{\tilde \mu_j}{w_j}, \tilde \Sigma_j = \frac{\tilde \Sigma_j}{w_j}, \;j = 1 : k&amp;lt;/math&amp;gt;&lt;br /&gt;
# вычисление  изменения логарифма правдоподобия&amp;lt;math&amp;gt;\Delta LL = fabs(\sum_{i=1}^m LL^{iter}_i - \sum_{i=1}^m LL^{iter - 1}_i)&amp;lt;/math&amp;gt; &lt;br /&gt;
# if (&amp;lt;math&amp;gt;\Delta LL &amp;lt; \varepsilon&amp;lt;/math&amp;gt;) then break;&lt;br /&gt;
# end for&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&amp;lt;b&amp;gt;E-шаг&amp;lt;/b&amp;gt;:&lt;br /&gt;
# вычисление обратной матрицы &amp;lt;math&amp;gt;\Sigma_j^{-1}, j = 1 : k&amp;lt;/math&amp;gt; при фиксированном &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; для двумерного случая по явным формулам имеет сложность &amp;lt;math&amp;gt;O(d^2)&amp;lt;/math&amp;gt;, для всех кластеров — &amp;lt;math&amp;gt;O(d^2k)&amp;lt;/math&amp;gt;&lt;br /&gt;
# вычисление &amp;lt;math&amp;gt;g_{ij}, i = 1 : m, j = 1 : k&amp;lt;/math&amp;gt; при фиксированных &amp;lt;math&amp;gt;i, j&amp;lt;/math&amp;gt; имеет сложность &amp;lt;math&amp;gt;O(d)&amp;lt;/math&amp;gt;, сложность вычисления матрицы G — &amp;lt;math&amp;gt;O(dmk)&amp;lt;/math&amp;gt;&lt;br /&gt;
# вычисление &amp;lt;math&amp;gt;LL_i, i = 1 : m&amp;lt;/math&amp;gt; при фиксированном &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; имеет сложность &amp;lt;math&amp;gt;O(k)&amp;lt;/math&amp;gt;, для всех объектов имеет сложность &amp;lt;math&amp;gt;O(mk)&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;b&amp;gt;M-шаг&amp;lt;/b&amp;gt;:&lt;br /&gt;
# вычисление &amp;lt;math&amp;gt;w_j,  j = 1 : k&amp;lt;/math&amp;gt; при фиксированном &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; имеет сложность &amp;lt;math&amp;gt;O(m)&amp;lt;/math&amp;gt;, для весов всех кластеров — &amp;lt;math&amp;gt;O(mk)&amp;lt;/math&amp;gt;&lt;br /&gt;
# вычисление &amp;lt;math&amp;gt;\mu_j, j = 1 : k&amp;lt;/math&amp;gt; при фиксированном &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; имеет сложность &amp;lt;math&amp;gt;O(dm)&amp;lt;/math&amp;gt;, для всех кластеров — &amp;lt;math&amp;gt;O(dmk)&amp;lt;/math&amp;gt;&lt;br /&gt;
# вычисление &amp;lt;math&amp;gt;\Sigma_j, j = 1 : k&amp;lt;/math&amp;gt; при фиксированном &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; имеет сложность &amp;lt;math&amp;gt;O(d^2m)&amp;lt;/math&amp;gt;, для всех кластеров — &amp;lt;math&amp;gt;O(d^2mk)&amp;lt;/math&amp;gt;&lt;br /&gt;
# нормировка &amp;lt;math&amp;gt;w&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\mu_j = \frac{\mu_j}{w_j}, \Sigma_j = \frac{\Sigma_j}{w_j}, j = 1 : k&amp;lt;/math&amp;gt; имеет сложность &amp;lt;math&amp;gt;O(k)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;O(dk)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;O(d^2k)&amp;lt;/math&amp;gt;&lt;br /&gt;
# вычисление  изменения логарифма правдоподобия&amp;lt;math&amp;gt;\Delta LL&amp;lt;/math&amp;gt; имеет сложность &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Сложность алгоритма на одной итерации&amp;lt;/b&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O(k(d^2+dm+m+m+dm+d^2m+1+d+d^2)) = O(d^2mk)&amp;lt;/math&amp;gt;, так как мы рассматриваем задачу для двумерного случая, то есть &amp;lt;math&amp;gt;d=2&amp;lt;/math&amp;gt;, множитель &amp;lt;math&amp;gt;d^2&amp;lt;/math&amp;gt; можно отнести в константу, итоговая сложность вычисления на одной итерации &amp;lt;math&amp;gt;O(mk)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Для &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; итераций итоговая сложность алгоритма будет равна&amp;lt;/b&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O(mkn)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; — число объектов, &amp;lt;math&amp;gt;k&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;
Опишем граф алгоритма для следующих входных данных: &amp;lt;math&amp;gt;m = 3,\; k = 2,\; d = 2&amp;lt;/math&amp;gt;, то есть 3 входных объекта и 2 кластера. &lt;br /&gt;
&lt;br /&gt;
На рис.1 показана макроструктура EM-алгоритма. Входными данными в таком случае являются матрица &amp;lt;math&amp;gt;X \in \R^{3 \times 2}&amp;lt;/math&amp;gt; и число кластеров &amp;lt;math&amp;gt;k = 2&amp;lt;/math&amp;gt;. &lt;br /&gt;
На шаге &amp;lt;math&amp;gt;\mathbf{init}&amp;lt;/math&amp;gt; происходит инициализация начальных приближений параметров модели и затем итеративное повторение &amp;lt;math&amp;gt;\mathbf{E}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\mathbf{M}&amp;lt;/math&amp;gt; шагов алгоритма. &lt;br /&gt;
&lt;br /&gt;
[[file:EM.png|thumb|center|300px|Рис.1. Граф EM-алгоритма с отображением входных и выходных данных]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;E-шаг.&amp;lt;/b&amp;gt; На рис.2 детально изображена схема E-шага. &lt;br /&gt;
Входные параметры &amp;lt;math&amp;gt;x_1,\; x_2,\; x_3 \in \R^{1 \times 2}&amp;lt;/math&amp;gt; являются строчками входной матрицы &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt;, также на вход подаются текущие приближения векторов средних значений (&amp;lt;math&amp;gt;\mu_1, \;\mu_2&amp;lt;/math&amp;gt;), матриц ковариаций (&amp;lt;math&amp;gt;\Sigma_1, \Sigma_2&amp;lt;/math&amp;gt;) и весов &amp;lt;math&amp;gt;w&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Вершинами &amp;lt;math&amp;gt;\mathbf{eI}&amp;lt;/math&amp;gt; обозначена операция нахождения обратной матрицы &amp;lt;math&amp;gt;\Sigma_j^{-1},\; j = 1,2&amp;lt;/math&amp;gt;. Вершины группы &amp;lt;math&amp;gt;\mathbf{eS}&amp;lt;/math&amp;gt; обозначают вычитание векторов &amp;lt;math&amp;gt;x_i - \mu_j,\; i = 1,2,3; \; j = 1, 2&amp;lt;/math&amp;gt;. Салатовые узлы графа &amp;lt;math&amp;gt;\mathbf{eE}&amp;lt;/math&amp;gt; обозначают вычисление ненормированного значения &amp;lt;math&amp;gt;g_{ij}, \;i = 1,2,3;\;j=1,2&amp;lt;/math&amp;gt; по формулам из раздела [[#Схема реализации последовательного алгоритма|описания алгоритма]]. Далее выход вершин этой группы подаётся на вход вершинам &amp;lt;math&amp;gt;\mathbf{eN}&amp;lt;/math&amp;gt;, которые обозначают нормировку, затем в &amp;lt;math&amp;gt;\mathbf{eL}&amp;lt;/math&amp;gt; происходит подсчет логарифма правдоподобия. На выходе этого графа получаются скрытые переменные &amp;lt;math&amp;gt;g_{ij}&amp;lt;/math&amp;gt; и логарифм правдоподобия LL.&lt;br /&gt;
 &lt;br /&gt;
[[file:EM_E_step.png|thumb|center|500px|Рис.2. Граф E-шага с отображением входных и выходных данных]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;M-шаг.&amp;lt;/b&amp;gt; На рисунке 3 изображена схема M-шага.&lt;br /&gt;
Входными параметрами являются: исходные объекты &amp;lt;math&amp;gt;x_1,\; x_2,\; x_3 \in \R^{1 \times 2}&amp;lt;/math&amp;gt;, скрытые переменные &amp;lt;math&amp;gt;g_{11},\;g_{21},\;g_{31},\;\mu_1&amp;lt;/math&amp;gt; для пересчета параметров первого кластера и &amp;lt;math&amp;gt;g_{12},\;g_{22},\;g_{32},\;\mu_2&amp;lt;/math&amp;gt; — для второго.&lt;br /&gt;
&lt;br /&gt;
Вершина &amp;lt;math&amp;gt;\mathbf{m}\boldsymbol{\mu}&amp;lt;/math&amp;gt; обозначает подсчет слагаемого математического ожидания для одного объекта, затем на шаге &amp;lt;math&amp;gt;\mathbf{mS_1}&amp;lt;/math&amp;gt; происходит суммирование слагаемых, и, наконец, на шаге &amp;lt;math&amp;gt;\mathbf{mN_1}&amp;lt;/math&amp;gt; нормировка математического ожидания, выходом являются &amp;lt;math&amp;gt;\mu_1,\;\mu_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
Вершина &amp;lt;math&amp;gt;\mathbf{m}\boldsymbol{\Sigma}&amp;lt;/math&amp;gt; обозначает подсчет слагаемого матрицы ковариации для одного объекта, затем на шаге &amp;lt;math&amp;gt;\mathbf{mS_2}&amp;lt;/math&amp;gt; происходит суммирование слагаемых, и, наконец, на шаге &amp;lt;math&amp;gt;\mathbf{mN_2}&amp;lt;/math&amp;gt; нормировка матрицы ковариации, выходом являются &amp;lt;math&amp;gt;\Sigma_1,\;\Sigma_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
Операция &amp;lt;math&amp;gt;\mathbf{mS_3}&amp;lt;/math&amp;gt; обозначает вычисление ненормированного веса для одного шага, затем при выполнении &amp;lt;math&amp;gt;\mathbf{mN_3}&amp;lt;/math&amp;gt; происходит нормировка весов, выходом являются &amp;lt;math&amp;gt;w_1,\;w_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[file:EM_M_step.png|thumb|center|500px|Рис.3. Граф M-шага с отображением входных и выходных данных]]&lt;br /&gt;
&lt;br /&gt;
На рис.1 показана структура ЕM-алгоритма для кластеризации, на рис.2 — структура E-шага  и на рис.3 — структура M-шага.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Как видно из информационного графа, возможно распараллеливание как по кластерам, так и по объектам. Однако, в реальных задачах число кластеров много меньше числа объектов, поэтому распараллеливание по кластерам нецелесообразно.&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается вариант распараллеливания по объектам. Стоит отметить, что важно корректно организовать работу с параметрами модели (матрицами ковариаций, средними значениями и весами), чтобы не произошло ситуации гонки за ресурсами &amp;lt;ref&amp;gt;Воеводин В.В., Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: плотная вещественная матрица объектов-признаков &amp;lt;math&amp;gt;X \in \R^{m \times d}&amp;lt;/math&amp;gt; и количество кластеров &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; — количество объектов, &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; — количество кластеров.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;m \times d + 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: вектор весов &amp;lt;math&amp;gt;w \in \R^{k \times 1}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\;\;k&amp;lt;/math&amp;gt; векторов математических ожиданий &amp;lt;math&amp;gt;\mu_j \in \R^{d \times 1}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\;\;k&amp;lt;/math&amp;gt; матриц ковариации &amp;lt;math&amp;gt;\Sigma \in \R^{d \times d}&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;k \times (d \times d + d + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
EM-алгоритм не является устойчивым, результат его работы сильно зависит от начальных приближений параметров. При неудачном выборе начальных приближений алгоритм может не сойтись или сойтись  в локальный экстремум. &lt;br /&gt;
&lt;br /&gt;
Также, алгоритм не является детерминированным. Так как в начале работы алгоритма происходит инициализация начальных параметров случайным образом (с учетом положительной определенности и симметричности матрицы ковариации), он не может быть детерминирован.&lt;br /&gt;
&lt;br /&gt;
Алгоритм сбалансирован по E и M шагам, затраты на выполнение этих этапов примерно одинаковы.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
В данном разделе приведем код реализации последовательного алгоритма.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot;&amp;gt;&lt;br /&gt;
double_vector em_algo::expectation_step(double_matrix&amp;amp; features)&lt;br /&gt;
{&lt;br /&gt;
    long n_objects = features.size1();&lt;br /&gt;
    int n_clusters = parameters.sigmas.size();&lt;br /&gt;
    double pi = boost::math::constants::pi&amp;lt;double&amp;gt;();&lt;br /&gt;
&lt;br /&gt;
    // precalculate inverse matrices and dets&lt;br /&gt;
    std::vector&amp;lt;double_matrix&amp;gt; sigmas_inverted(n_clusters);&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt; norm_distribution_denominator(n_clusters);&lt;br /&gt;
    for (int i = 0; i &amp;lt; n_clusters; ++i)&lt;br /&gt;
    {        &lt;br /&gt;
        double_matrix sigma_inverted(parameters.sigmas[i].size1(), parameters.sigmas[i].size2());&lt;br /&gt;
        double det = InvertMatrix(parameters.sigmas[i], sigma_inverted);&lt;br /&gt;
        if (det == 0)&lt;br /&gt;
        {&lt;br /&gt;
            std::cerr &amp;lt;&amp;lt; &amp;quot;Matrix can not be inverted\n&amp;quot;;&lt;br /&gt;
            exit(1);&lt;br /&gt;
        }&lt;br /&gt;
        norm_distribution_denominator[i] = sqrt(pow(2 * pi, parameters.n_features) * det);&lt;br /&gt;
        sigmas_inverted[i] = sigma_inverted;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    hidden_vars = double_matrix(n_objects, n_clusters);&lt;br /&gt;
    double_vector log_likelihood(n_objects, 0);&lt;br /&gt;
&lt;br /&gt;
    for (auto i = 0; i &amp;lt; n_objects; ++i)&lt;br /&gt;
    {&lt;br /&gt;
        double_matrix_row x(features, i);&lt;br /&gt;
        double norm_value = 0;&lt;br /&gt;
        for (auto j = 0; j &amp;lt; n_clusters; ++j)&lt;br /&gt;
        {&lt;br /&gt;
            double_matrix_column current_means(parameters.means, j);&lt;br /&gt;
            double_vector x_centered = x - current_means;&lt;br /&gt;
&lt;br /&gt;
            double exp_power = -0.5 * inner_prod(prod(x_centered, sigmas_inverted[j]), x_centered);&lt;br /&gt;
            hidden_vars(i, j) = parameters.weights(j) * exp(exp_power) / norm_distribution_denominator[j];&lt;br /&gt;
&lt;br /&gt;
            norm_value += hidden_vars(i, j);&lt;br /&gt;
        }&lt;br /&gt;
        double_matrix_row hidden_vars_row(hidden_vars, i);&lt;br /&gt;
        if (norm_value != 0)&lt;br /&gt;
        {&lt;br /&gt;
            hidden_vars_row = hidden_vars_row / norm_value;&lt;br /&gt;
            log_likelihood(i) = log(inner_prod(hidden_vars_row, parameters.weights));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    return log_likelihood;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void em_algo::maximization_step(double_matrix&amp;amp; features)&lt;br /&gt;
{&lt;br /&gt;
    int n_objects = features.size1();&lt;br /&gt;
&lt;br /&gt;
    double_vector w = double_vector(n_clusters, 0.0);&lt;br /&gt;
    double_matrix means = double_matrix(parameters.n_features, n_clusters, 0.0);&lt;br /&gt;
    std::vector&amp;lt;double_matrix&amp;gt; sigmas;&lt;br /&gt;
    for (int j = 0; j &amp;lt; n_clusters; ++j)&lt;br /&gt;
        sigmas.push_back(double_matrix(parameters.n_features, parameters.n_features, 0.0));&lt;br /&gt;
&lt;br /&gt;
    for (int i = 0; i &amp;lt; n_objects; ++i)&lt;br /&gt;
    {&lt;br /&gt;
        double_matrix_row x_i = row(features, i);&lt;br /&gt;
&lt;br /&gt;
        for (int j = 0; j &amp;lt; n_clusters; ++j)&lt;br /&gt;
        {&lt;br /&gt;
            double g = hidden_vars(i, j);&lt;br /&gt;
            w(j) += g;&lt;br /&gt;
&lt;br /&gt;
            double_matrix_column single_mean = column(means, j);&lt;br /&gt;
&lt;br /&gt;
            single_mean += g * x_i;&lt;br /&gt;
&lt;br /&gt;
            double_vector x_centered = x_i - column(parameters.means, j);&lt;br /&gt;
            for (int k = 0; k &amp;lt; parameters.n_features; ++k)&lt;br /&gt;
                for (int l = 0; l &amp;lt; parameters.n_features; ++l)&lt;br /&gt;
                    sigmas[j](k, l) = sigmas[j](k, l) + g * x_centered(k) * x_centered(l);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    // update weights&lt;br /&gt;
    parameters.weights = w / n_objects;&lt;br /&gt;
&lt;br /&gt;
    for (int j = 0; j &amp;lt; n_clusters; ++j) {&lt;br /&gt;
        double weight = w(j);&lt;br /&gt;
        // update means&lt;br /&gt;
        double_matrix_column means_old = column(parameters.means, j);&lt;br /&gt;
        double_matrix_column means_new = column(means, j);&lt;br /&gt;
        means_old = means_new / weight;&lt;br /&gt;
&lt;br /&gt;
        // update sigmas&lt;br /&gt;
        parameters.sigmas[j] = sigmas[j] / weight;&lt;br /&gt;
        for (int k = 0; k &amp;lt; parameters.n_features; ++k)&lt;br /&gt;
            parameters.sigmas[j](k, k) = parameters.sigmas[j](k, k) + tol;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
bool em_algo::is_likelihood_stabilized(double_vector likelihood, double_vector previous_likelihood)&lt;br /&gt;
{&lt;br /&gt;
    double likelihood_diff = sum(likelihood) - sum(previous_likelihood);&lt;br /&gt;
    return fabs(likelihood_diff) &amp;lt; tol;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
model em_algo::process(double_matrix&amp;amp; features, int max_iterations)&lt;br /&gt;
{&lt;br /&gt;
    int iteration = 0;&lt;br /&gt;
    double_vector likelihood, previous_likelihood;&lt;br /&gt;
    while (iteration++ &amp;lt; max_iterations &amp;amp;&amp;amp; (iteration &amp;lt;= 2 || !is_likelihood_stabilized(likelihood, previous_likelihood)))&lt;br /&gt;
    {&lt;br /&gt;
        previous_likelihood = likelihood;&lt;br /&gt;
        likelihood = expectation_step(features);&lt;br /&gt;
        maximization_step(features);&lt;br /&gt;
    }&lt;br /&gt;
    return parameters;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Возможной реализацией является перестановка местами циклов по объектам и по кластерам на E и М шаге. В данном случае внешний цикл проходит по объектам, так как подразумевается дальнейшая реализации распараллеливания по объектам. При реализации только последовательного алгоритма более понятной версией будет реализация внешнего цикла по кластерам, и внутреннего по объектам, но такая реализация увеличит число обращений в память и общее время работы алгоритма.&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;k = 4 &amp;lt;/math&amp;gt;, и, также, было зафиксировано ядро рандомизации, чтобы избавиться от случайности различного выбора начального приближения параметров. Для показательности результатов условие досрочного завершения работы алгоритма в случае стабилизации логарифма правдоподобия игнорировалось, и для каждого запуска проводилось 50 итераций EM-алгоритма.&lt;br /&gt;
&lt;br /&gt;
Для экспериментов было сгенерировано 20 выборок разного размера: от 40000 объектов до 200000 с шагом в 10000. Для каждой выборки время работы алгоритма усреднялось по нескольким запускам, чтобы избежать выбросов.&lt;br /&gt;
&lt;br /&gt;
Для работы с многопоточностью использовалась библиотека OpenMP. С помощью нее были распараллелены основные циклы по объектам на E и M шаге.&lt;br /&gt;
&lt;br /&gt;
Эксперименты проводились на компьютере с процессором Intel(R) Core(TM) i7-5820K @ 3.30GHz, который поддерживает до 12ти потоков.&lt;br /&gt;
&lt;br /&gt;
Как видно на рис. 4, производительность растет до 12 процессов, после чего время работы алгоритма снова начинает увеличиваться, то есть использование более 12 процессов при рассматриваемой конфигурации процессора не имеет смысла. Заметим также, что в увеличением числа точек, скорость работы программы линейно увеличивается.&lt;br /&gt;
&lt;br /&gt;
[[file:EM performance.png|thumb|center|700px|Рис. 4 Время работы EM алгоритма в зависимости от числа процессов и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
В результате проведённых экспериментов был получен следующий диапазон эффективности реализации алгоритма:&lt;br /&gt;
&lt;br /&gt;
*	минимальная эффективность реализации 0,00072%;&lt;br /&gt;
*	максимальная эффективность реализации 25.5037%.&lt;br /&gt;
&lt;br /&gt;
[[file:EM_Efficiency.png|thumb|center|700px|Рис. 4 Эффективность EM алгоритма в зависимости от числа процессов и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Существуют следующие последовательные реализации EM-алгоритма для кластеризации: [http://docs.opencv.org/2.4/modules/ml/doc/expectation_maximization.html# opencv], [http://scikit-learn.org/stable/modules/mixture.html scikit-learn]. &lt;br /&gt;
&lt;br /&gt;
Также существует несколько параллельных реализаций, описанных в следующих статьях:&lt;br /&gt;
&lt;br /&gt;
В статье &amp;lt;ref&amp;gt;López-de-Teruel P. E., García J. M., Acacio; The Parallel EM Algorithm and its Applications in Computer Vision&amp;lt;/ref&amp;gt;  авторы предлагают распределить вычисление скрытых переменных для каждого объекта между процессорами и на каждой итерации производить нормализацию. M-шаг предлагается параллелить по компонентам, что требует реализации корректного взаимодействия между процессорами. Предложенный вариант распараллеливания был реализован и протестирован авторами статьи с помощью MPI библиотеки MPICH. &lt;br /&gt;
&lt;br /&gt;
Авторы статьи &amp;lt;ref&amp;gt;Abhinandan Das, Mayur Datar, Ashutosh Garg; Google News Personalization: Scalable Online Collaborative Filtering&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&amp;lt;/ref&amp;gt; используют MapReduce для распараллеливания EM-алгоритма для PLSI моделей.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;/div&gt;</summary>
		<author><name>Algoman</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%9C%D0%B0%D1%80%D0%B8%D1%8F_%D0%93%D0%BE%D1%82%D0%BC%D0%B0%D0%BD&amp;diff=17599</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%9C%D0%B0%D1%80%D0%B8%D1%8F_%D0%93%D0%BE%D1%82%D0%BC%D0%B0%D0%BD&amp;diff=17599"/>
		<updated>2016-11-16T11:24:04Z</updated>

		<summary type="html">&lt;p&gt;Algoman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Замечания второго рецензента ==&lt;br /&gt;
1) Проверьте орфографию - нашел слова &amp;quot;вычисляеются&amp;quot;, &amp;quot;вычЕсленные&amp;quot;&lt;br /&gt;
&lt;br /&gt;
2) П1.2 Разъясните по поводу входной матрицы m на d. Что такое m, что такое d? При кластеризации более привычно говорить о наборе входных объектов&lt;br /&gt;
&lt;br /&gt;
3) Там же. Нужно больше пояснений по Е и М шагам. Сейчас одни формулы. Что такое N(*,*,*) и p()?&lt;br /&gt;
&lt;br /&gt;
4) П 1.5 Надо добавить - как вычисляется дельта LL.&lt;br /&gt;
&lt;br /&gt;
5) П 1.7 Информационный граф нужно строить для общего случая, а не при конкретных значениях параметров.&lt;br /&gt;
&lt;br /&gt;
6) П 1.9 Что подразумевается под меткой кластера?&lt;br /&gt;
&lt;br /&gt;
7) П 1.10 Определение вычислительной мощности алгоритма здесь неуместно. Этот пункт посвящен свойствам алгоритма&lt;br /&gt;
&lt;br /&gt;
== Замечания к [[Алгоритм_кластеризации,_основанный_на_максимизации_ожидания]] ==&lt;br /&gt;
&lt;br /&gt;
1) список литературы лучше оформить средствами разметки - см. как сделано в [[Разложение_Холецкого_(метод_квадратного_корня)]]&lt;br /&gt;
&lt;br /&gt;
Список литературы исправлен.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Замечения от 31.10 ==&lt;br /&gt;
&lt;br /&gt;
&amp;quot;- В конце статьи должен быть приведен список всех источников, откуда бралась информация по алгоритму. Если вы используется готовый рисунок, то сслыку на источник нужно разместить либо в подписи к рисунку, либо в тексте, где стоит ссылка на рисунок.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
какой источник картинок с графиками (п1.1 и 2.4)? созданы ли они авторами для этой статьи, публиковались ли где-то ещё?&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Все рисунки создавались авторами статьи, исходники есть, больше нигде не публиковались.&lt;br /&gt;
&lt;br /&gt;
== Замечания к пункту 2.4 от 16.11.2016 == &lt;br /&gt;
&lt;br /&gt;
* зачем выделен подпункт 2.4.1 с дублирующим заголовком?&lt;br /&gt;
* оба рисунка - номер 4&lt;br /&gt;
* подписи к первому рисунку 4 практически не читаются&lt;br /&gt;
* &amp;quot;Как видно на рис. 4, производительность растет до 12 процессов, после чего время работы алгоритма снова начинает увеличиваться...&amp;quot; на рисунке не видно, что происходит после 12 процессов - следует переформулировать предложение&lt;/div&gt;</summary>
		<author><name>Algoman</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:Noite/EM-%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8&amp;diff=17598</id>
		<title>Участник:Noite/EM-алгоритм кластеризации</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:Noite/EM-%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8&amp;diff=17598"/>
		<updated>2016-11-16T11:16:26Z</updated>

		<summary type="html">&lt;p&gt;Algoman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = EM-алгоритм кластеризации&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(iter * N * M^2 * K)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;N * M + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(iter * M^2 * K)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(iter * N)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Автор описания: [[Участник:Noite|Зинченко Д.А.]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритма =&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
В задачах оптимизации EM-алгоритмом называют итеративную процедуру поиска численного значения экстремума какой-либо функции. В частности, в статистике этот алгоритм используется для оценки максимального правдоподобия. Впервые название EM-алгоритм было предложено в 1977 году&amp;lt;ref&amp;gt;A. Dempster, N. Laird and D. Rubin. Maximum likelihood estimation from incomplete data. – Journal of the Royal Statistical Society, Series B, 1977, vol. 39, p. 1-38.&amp;lt;/ref&amp;gt;, однако его идеи были описаны и раньше&amp;lt;ref name=korolev&amp;gt;В.Ю.Королёв. ЕМ-алгоритм, его модификации и их применение к задаче разделения смесей вероятностных распределений.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
EM-алгоритм применяется для решения задач двух типов &amp;lt;ref name=korolev/&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
# Анализ неполных данных (данных с пропусками). &lt;br /&gt;
# Оценка максимального правдоподобия в случае, если функцию правдоподобия трудно исследовать аналитически. В этом случае введение набора скрытых переменных может существенно упростить задачу.&lt;br /&gt;
&lt;br /&gt;
Задача кластеризации относится к задачам второго типа. В данной статье рассматривается следующая постановка задачи кластеризации:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;Дано множество из N объектов, каждый из которых представляет собой точку в M-мерном метрическом пространстве. Каждому измерению пространства соответствует некоторое свойство объекта. Необходимо разбить это множество на K подмножеств (кластеров) так, чтобы, чтобы элементы каждого подмножества существенно отличались по свойствам от элементов других подмножеств.&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Использование алгоритма EM подразумевает следующее &#039;&#039;предположение об объектах&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
Пусть объекты, которые необходимо разбить на кластеры, появляются случайным образом и независимо друг от друга согласно вероятностному распределению, равному смеси (линейной комбинации) распределений кластеров. В данной статье в дальнейшем будет считаться, что распределение каждого кластера является многомерным нормальным распределением с произвольной матрицей ковариации - наиболее часто используемое предположение.&lt;br /&gt;
&lt;br /&gt;
Тогда каждый объект принадлежит каждому кластеру, но с разной вероятностью. EM-алгоритм итеративно оценивает параметры распределений кластеров, максимизируя логарифмическую функцию максимального правдоподобия. После окончания работы алгоритма объект будет отнесен к кластеру, вероятность принадлежности которому максимальна. Вводимый набор скрытых переменных для каждого объекта - вероятности того, что объект принадлежит каждому из кластеров.&lt;br /&gt;
&lt;br /&gt;
Итерация алгоритма состоит из двух последовательных шагов.&lt;br /&gt;
&lt;br /&gt;
# (Expectation) Вычисляются новые ожидаемые значения скрытых переменных.&lt;br /&gt;
# (Maximization) Решается задача максимизации правдоподобия: По текущим значениям скрытых переменных обновляются параметры распределений для кластеров: математическое ожидание, дисперсия и вероятность появления объектов из кластера.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Используемые обозначения:&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - количество объектов, &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество параметров объекта&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma_{n,k}&amp;lt;/math&amp;gt; - значения скрытых переменных&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;N_{k}&amp;lt;/math&amp;gt; - количество элементов отнесенных к кластеру &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x_{1},...,x_N&amp;lt;/math&amp;gt; - объекты&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Параметры распределений:&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;w_{1},...,w_{K}&amp;lt;/math&amp;gt; - вероятности появления объектов из кластеров (веса кластеров), &amp;lt;math&amp;gt;\sum_{k=1}^Kw_{k}=1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\mu_{1},...,\mu_{K}&amp;lt;/math&amp;gt; - центры гауссиан кластеров&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\Sigma_{1},...,\Sigma_{K}&amp;lt;/math&amp;gt; - матрицы ковариации гауссиан кластеров, каждая матрица имеет размерность &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;x&amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Смесь распределений:&#039;&#039;&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt; P(x) = \sum_{j=1}^Kw_jp(x|\mu_{j}, \Sigma_{j})&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Цель алгоритма - вычислить параметры распределений, максимизирующих логарифм функции правдоподобия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;\ln P(x|w,\mu,\Sigma)= \sum_{n=1}^N \ln \{ \sum_{k=1}^K w_{k}p(x_{n}|\mu_{k},\Sigma_{k})\}&amp;lt;/math&amp;gt;.&amp;lt;/center&amp;gt;  &lt;br /&gt;
&lt;br /&gt;
* В начале работы алгоритма задаются параметры начального приближения:&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;w_{i} = 1/K, \mu_{i} = random(x_{j}), i=1..K, j=1..N&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;\Sigma_{j,j}^{k}=\frac{1}{NK}\sum_{i=1}^N(x_{i,j} - \mu_{k,j})^2, k=1..K, j=1..M&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Поскольку от начального приближения может сильно зависеть результат работы алгоритма, вместо инициализации кластеров случайными центрами, равными весами и диагональными матрицами ковариации, как в приведенных формулах, часто применяют другие способы (подробнее - в [[#Особенности реализации последовательного алгоритма | особенностях реализации]])&#039;&#039;&lt;br /&gt;
* Далее итеративно выполняется следующая пара процедур:&lt;br /&gt;
** E-шаг: используя текущее значение параметров &amp;lt;math&amp;gt;w_{1},...,w_{k};\mu_{1},...,\mu_{k};\Sigma^{1},...,\Sigma^{k}&amp;lt;/math&amp;gt;, вычисляем значение вектора скрытых переменных &amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt;:&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;\gamma_{n,k}=\frac{w_{k}p(x_{n}|\mu_{k},\Sigma^{k})}{\sum_{j=1}^K w_{j}p(x_{n}|\mu_{j},\Sigma^{j})}, &amp;lt;/math&amp;gt; знаменатель дроби - нормировочный коэффициент&amp;lt;/center&amp;gt;&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;p(x|\mu,\Sigma)=\frac{1}{{(2\pi)}^{\frac{N}{2}}\sqrt{|\Sigma|}}exp\biggl\{-\frac{1}{2}{(x-\mu)}^T{\Sigma}^{-1}(x-\mu)\biggr\}&amp;lt;/math&amp;gt; - плотность &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;-мерного нормального распределения&amp;lt;/center&amp;gt;&lt;br /&gt;
** М-шаг: переоценка параметров по текущим значениям скрытых переменных для &amp;lt;math&amp;gt;k = 1..K&amp;lt;/math&amp;gt;:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;\mu^{new}_{k}=\frac{1}{N_{k}}\sum_{n=1}^N \gamma_{n,k}x_{n}&amp;lt;/math&amp;gt;,&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;\Sigma_{new}^{k}=\frac{1}{N_{k}}\sum_{n=1}^N \gamma_{n,k} (x_{n}-\mu_{k}^{new})(x_{n}-\mu_{k}^{new})^{T}&amp;lt;/math&amp;gt;,&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;w_{k}^{new}=\frac{N_{k}}{N}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;N_{k}=\sum_{n=1}^N \gamma_{n,k}&amp;lt;/math&amp;gt;.&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В EM алгоритме используется один из следующих критериев остановки:&lt;br /&gt;
*Норма разности векторов скрытых переменных на текущей итерации не превышает заданную константу &lt;br /&gt;
*Прошествие заданного количества итераций&lt;br /&gt;
*Изменение логарифмического правдоподобия меньше заданной константы.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро алгоритма состоит из двух шагов, повторяющихся каждую итерацию:&lt;br /&gt;
*Обновление скрытых переменных на основе текущих параметров распределений&lt;br /&gt;
*Обновление параметров кластеров: весов, центров и матриц ковариации&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как записано в [[#Вычислительное ядро алгоритма|описании вычислительного ядра алгоритма]], основную часть алгоритма составляют итеративно проводимые макрооперации: Expectation шаг - вычисление новых значений скрытых переменных, Maximization шаг - обновление параметров кластеров. Макроструктура алгоритма представлена на рисунке 1:&lt;br /&gt;
[[file:EM_macro.png|thumb|center|600px|Рисунок 1: Макроструктура EM-алгоритма]]&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Примерная схема реализации EM алгоритма с предварительной обработкой матриц ковариации:&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
Инициализировать веса и центры кластеров;&lt;br /&gt;
Инициализировать матрицы ковариации;&lt;br /&gt;
&lt;br /&gt;
// Основной цикл&lt;br /&gt;
Пока условие остановки не выполнено&lt;br /&gt;
    // E-шаг&lt;br /&gt;
    В цикле для каждого кластера&lt;br /&gt;
        Вычислить определитель матрицы ковариации Sigma;&lt;br /&gt;
        Вычислить обратную матрицу матрице Sigma;&lt;br /&gt;
    В цикле для каждого объекта&lt;br /&gt;
        В цикле для каждого кластера&lt;br /&gt;
            Вычислить и запомнить p(x | mu, Sigma) для текущего объекта и кластера;&lt;br /&gt;
        Просуммировать вычисленные p(x | mu, Sigma);&lt;br /&gt;
        В цикле для каждого кластера&lt;br /&gt;
            Обновить скрытые переменные gamma;&lt;br /&gt;
    // M-шаг&lt;br /&gt;
    Обновить веса w;&lt;br /&gt;
    Обновить центры кластеров mu;&lt;br /&gt;
    Обновить матрицы ковариации Sigma;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Количество итераций алгоритма зависит от условия остановки, поэтому будем рассматривать сложность одной итерации.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Шаг E&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Сложность вычисления определителя произвольной матрицы ковариации &amp;lt;math&amp;gt;\Sigma&amp;lt;/math&amp;gt; методом Гаусса - &amp;lt;math&amp;gt;O(M^3)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Сложность вычисления матрицы, обратной произвольной матрице ковариации &amp;lt;math&amp;gt;\Sigma&amp;lt;/math&amp;gt; методом Гаусса - &amp;lt;math&amp;gt;O(M^3)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Сложность предварительного вычисления определителей и обратных матриц матрицам ковариации - &amp;lt;math&amp;gt;O(K * M^3)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С учетом заранее вычисленных определителей и обратных матриц сложность вычисления &amp;lt;math&amp;gt;p(x | \mu,\Sigma)&amp;lt;/math&amp;gt; составит: &amp;lt;math&amp;gt;O(M^2)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Суммарно сложность шага E составит &amp;lt;math&amp;gt;O(N * M^2 * K + K * M^3)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Шаг M&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Сложность обновления весов кластеров &amp;lt;math&amp;gt;O(K * N)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Сложность обновления центров кластеров &amp;lt;math&amp;gt;O(K * M * N)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Сложность обновления одной матрицы ковариации &amp;lt;math&amp;gt;O(N * M)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Сложность обновления всех матриц ковариации &amp;lt;math&amp;gt;O(K * M * N)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Суммарно сложность шага M алгоритма - &amp;lt;math&amp;gt;O(K * M * N)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Таким образом, сложность одной итерации EM алгоритма для псевдокода, указанного в предыдущем разделе, составит &amp;lt;math&amp;gt;O(K * M^2 * N + K * M^3 + K * M * N)&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
В предположении, что размерность объектов много меньше их количества &amp;lt;math&amp;gt;M &amp;lt;&amp;lt; N&amp;lt;/math&amp;gt; получим сложность итерации &amp;lt;math&amp;gt;O(K * M^2 * N)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что вычисление определителя и обратной матрицы к произвольной матрице ковариации составляет большу́ю часть работы шага E и существенно влияет на его сложность. Поэтому эти вычисления проведены заранее - вынесены за основной цикл шага E&amp;lt;ref name=ParallelEMComparissonGraphLab&amp;gt;Henggang Cui, Jinliang Wei, Wei Dai. Parallel Implementation of Expectation-Maximization for Fast Convergence - School of Computer Science, Carnegie Mellon University. [https://users.ece.cmu.edu/~hengganc/archive/report/final.pdf]&amp;lt;/ref&amp;gt;. Помимо этого сложность этих вычислений можно сократить еще сильнее, если ввести ограничения структуру матрицы ковариации &amp;lt;math&amp;gt;\Sigma&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Наиболее часто используемым ограничением, позволяющим эффективно распараллеливать алгоритм&amp;lt;ref&amp;gt;Вячеслав Орешков. EМ — масштабируемый алгоритм кластеризации [https://basegroup.ru/community/articles/em]&amp;lt;/ref&amp;gt;, является предположение, что матрица ковариации имеет диагональную форму. Тогда вычисление её определителя и обратной матрицы имеет сложнось &amp;lt;math&amp;gt;O(M)&amp;lt;/math&amp;gt;, а суммарная сложность шага E и сложность всей итерации составит &amp;lt;math&amp;gt;O(K * M * N)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
Макроструктура алгоритма представлена на рисунке 1 (см. [[#Макроструктура алгоритма|раздел 1.4]] статьи).&lt;br /&gt;
&lt;br /&gt;
На рисунке 2 представлена схема вычислений E-шага алгоритма для одного объекта: для объекта &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; и параметров &amp;lt;math&amp;gt;w_{j}, \mu_{j}, \Sigma_{j}, j=1..K&amp;lt;/math&amp;gt; по формулам [[#Математическое описание алгоритма|раздела 1.2]] вычисляются ненормированные значения скрытых переменных &amp;lt;math&amp;gt;g_{j}&amp;lt;/math&amp;gt;, нормировочный коэффициент &#039;&#039;normСoeff&#039;&#039;, и получаются итоговые значения &amp;lt;math&amp;gt;\gamma_{i,j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[file:EM_Expectation_step.png|thumb|center|400px|Рисунок 2: E-шаг EM алгоритма для одного объекта]]&lt;br /&gt;
&lt;br /&gt;
На рисунке 3 представлена схема вычислений E-шага алгоритма для всех объектов: для объекта &amp;lt;math&amp;gt;x_{j}&amp;lt;/math&amp;gt; и параметров-векторов &amp;lt;math&amp;gt;w, \mu, \Sigma&amp;lt;/math&amp;gt; по формулам [[#Математическое описание алгоритма|раздела 1.2]] вычисляются значения скрытых переменных. &amp;lt;math&amp;gt;E_{i}, i=1..N&amp;lt;/math&amp;gt; - маркооперации, E-шаги для соответствующих объектов.&lt;br /&gt;
&lt;br /&gt;
[[file:EM_Expectation_step_all.png|thumb|center|400px|Рисунок 3: E-шаг EM алгоритма для всех объектов]]&lt;br /&gt;
&lt;br /&gt;
На рисунке 4 представлена схема вычислений M-шага алгоритма для одного кластера: для объектов &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; и скрытых переменных &amp;lt;math&amp;gt;\gamma_{i,j}&amp;lt;/math&amp;gt;, соответствующих степени принадлежности этих объектов кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;, согласно формулам шага M [[#Математическое описание алгоритма|раздела 1.2]] вычисляется нормировочный коэффициент &amp;lt;math&amp;gt;N_{j}&amp;lt;/math&amp;gt; и параметры этого кластера: вес &amp;lt;math&amp;gt;w_{j}^{new}&amp;lt;/math&amp;gt;, матрица ковариации &amp;lt;math&amp;gt;\Sigma_{j}^{new}&amp;lt;/math&amp;gt; и центр кластера &amp;lt;math&amp;gt;\mu_{j}^{new}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[file:EM_Maximization_step.png|thumb|center|400px|Рисунок 4: M-шаг EM алгоритма для одного кластера]]&lt;br /&gt;
&lt;br /&gt;
На рисунке 5 представлена схема вычислений M-шага алгоритма для всех кластеров. &amp;lt;math&amp;gt;M_{j}, j=1..K&amp;lt;/math&amp;gt; соответствует макрооперации - M-шагу для соответствующего кластера и скрытых переменных.&lt;br /&gt;
&lt;br /&gt;
[[file:EM_Maximization_step_all.png|thumb|center|400px|Рисунок 5: M-шаг EM алгоритма для всех кластеров]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Из схем вычислений шагов E и M шагов алгоритма, приведенным в [[#Информационный граф|предыдущем разделе]], видно, что если размерность матрицы ковариации небольшая (тогда вычисление определителя и обратной матрицы матрице ковариации не является трудоемкой операцией), обе макрооперации EM алгоритма можно распараллеливать как по кластерам, так и по объектам.&lt;br /&gt;
&lt;br /&gt;
Как правило количество кластеров, на которые нужно разбить объекты, несравнимо меньше количества объектов, поэтому распараллеливание в большинстве существующих реализаций происходит по объектам: обработка объектов по возможности равномерно распределяются по кластерам. Теоретически (если считать передачу данных между процессорами мгновенной) при наличии неограниченного числа процессоров сложность алгоритма составит &amp;lt;math&amp;gt;O(M^2 * K)&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;K&amp;lt;/math&amp;gt; - количество кластеров;&lt;br /&gt;
* Значения координат объектов &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; - &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; объектов с &amp;lt;math&amp;gt;M&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;N * M&amp;lt;/math&amp;gt; вещественных чисел (если координаты объектов - вещественные числа), &amp;lt;math&amp;gt;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;N&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;N&amp;lt;/math&amp;gt; целых неотрицательных чисел.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
=== Преимущества и недостатки ===&lt;br /&gt;
EM-алгоритм обладает следующими преимуществами и недостатками&amp;lt;ref&amp;gt;EM алгоритм, его модификации и обобщения. machinelearning.ru [http://www.machinelearning.ru/wiki/index.php?title=EM-%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC]&amp;lt;/ref&amp;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;
&#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;
[[file:DifferentCovariance.png|thumb|center|800px|Рисунок 6: Влияние структуры матрицы ковариации на форму кластеров для двумерного случая. a) - матрицы ковариации являются диагональными, b) - матрицы ковариации произвольны. &amp;lt;ref&amp;gt;Mathworks: Clustering Using Gaussian Mixture Models [http://www.mathworks.com/help/stats/clustering-using-gaussian-mixture-models.html]&amp;lt;/ref&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Рисунок 6 наглядно показывает, что при диагональной форме матриц ковариации полуоси эллипса (в общем случае - эллипсоида), соответствующего распределению объектов, отнесенных кластеру, параллельны осям координат объектов. В противном случае полуоси могут располагаться произвольным образом.&lt;br /&gt;
&lt;br /&gt;
=== Общие свойства ===&lt;br /&gt;
[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]] EM алгоритма равна &amp;lt;math&amp;gt;M * K * it&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - размерность объекта, &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; - количество кластеров, а &amp;lt;math&amp;gt;it&amp;lt;/math&amp;gt; - количество итераций. &lt;br /&gt;
&lt;br /&gt;
EM-алгоритм является итерационным, и число итераций в общем случае не фиксировано: оно зависит от условий остановки, начальных приближений и расположения объектов. Поэтому этот алгоритм &#039;&#039;недетерминированный&#039;&#039;. По тем же причинам EM-алгоритм является &#039;&#039;неустойчивым&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
=== Инициализация параметров распределений ===&lt;br /&gt;
Наиболее распространены 3 способа инициализации центров распределений для EM алгоритма:&lt;br /&gt;
# центр распределения совпадает со случайно выбранным объектом &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt;&lt;br /&gt;
# все наблюдения распределяются по кластерам случайным образом, а затем для каждого кластера пересчитывается цент соответствующего распределения&lt;br /&gt;
# центры кластеров получаются в результате работы алгоритма k-means. Использование такой инициализации оправдано тем, что k-means требует меньших вычислительных затрат и быстрее сходится&amp;lt;ref&amp;gt;EM алгоритм (пример) machinelearning.ru [http://www.machinelearning.ru/wiki/index.php?title=EM_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_(%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80])&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;
Многие статьи&amp;lt;ref name=FREERIDE&amp;gt;Leonid Glimcher, Gagan Agrawal. Parallelising EM Algorithm on a Cluster of SMPs [http://web.cse.ohio-state.edu/~agrawal/allpapers/europar04.pdf]&amp;lt;/ref&amp;gt;&amp;lt;ref name=CV&amp;gt;López-de-Teruel P. E., García J. M., Acacio; The Parallel EM Algorithm and its Applications in Computer Vision [http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.4.8470&amp;amp;rep=rep1&amp;amp;type=pdf]&amp;lt;/ref&amp;gt;&amp;lt;ref name=MULTITHREAD&amp;gt;Sharon X. Lee, Kaleb L. Leemaqz, Geoffrey J. McLachlan. A simple multithreaded implementation of the EM algorithm for mixture models [https://arxiv.org/pdf/1606.02054.pdf]&amp;lt;/ref&amp;gt;&amp;lt;ref name=CUDA&amp;gt;Araújo, G.F., H.T. Macedo, M.T. Chella, C.A.E. Montesco and M.V.O. Medeiros. PARALLEL IMPLEMENTATION OF EXPECTATION-MAXIMISATION ALGORITHM FOR THE TRAINING OF GAUSSIAN MIXTURE MODELS [https://ri.ufs.br/bitstream/123456789/1764/1/ExpectationMaximisationAlgorithm.pdf]&amp;lt;/ref&amp;gt;, в которых представлены параллельные реализации EM алгоритма, описывают помимо использующихся программных и аппаратных решений результаты проведенных экспериментов с данными. В качестве примера в этом разделе будут рассмотрены результаты эксперементов, проведенных со связующим программным обеспечением (&#039;&#039;middleware&#039;&#039;) FREERIDE&amp;lt;ref&amp;gt;Leonid Glimchera, Ruoming Jinb, Gagan Agrawala. Middleware for data mining applications on clusters and grids [http://www.cs.kent.edu/~jin/Papers/JPDC08.pdf]&amp;lt;/ref&amp;gt; (FRamework for Rapid Implementation of Datamining Engines), обеспечивающим возможность распараллеливания как для систем с общей памятью (в частности, симметричных мультипроцессорных систем), так и для систем с распределенной памятью.&lt;br /&gt;
&lt;br /&gt;
Эксперименты проводились на кластере машин Pentium 700MHz связанных при помощи Myrinet&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Myrinet&amp;lt;/ref&amp;gt; LANai 7.0 на трех наборах данных: &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;а)&#039;&#039;&#039; 3.3 * 10^6 объектов&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;b)&#039;&#039;&#039; 6.2 * 10^6 объектов&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;c)&#039;&#039;&#039; 12.5 * 10^6 объектов&lt;br /&gt;
&lt;br /&gt;
Объекты представляют собой координаты точек 10-мерного пространства.&lt;br /&gt;
 &lt;br /&gt;
Количество машин в кластере варьировалось от 1 до 8, при этом на каждой машине запускалось до четырех параллельных потоков.&lt;br /&gt;
&lt;br /&gt;
Результаты экспериментов представлены на рисунках 7-9&amp;lt;ref name=FREERIDE/&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
{|align=&amp;quot;center&amp;quot;&lt;br /&gt;
 |-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
 |[[file:EM_FREERIDE_experiments_a.png|thumb|center|350px|Рисунок 7: набор данных a)]]&lt;br /&gt;
 |[[file:EM_FREERIDE_experiments_b.png|thumb|center|357px|Рисунок 8: набор данных b)]]&lt;br /&gt;
 |[[file:EM_FREERIDE_experiments_c.png|thumb|center|351px|Рисунок 9: набор данных c)]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что используемые в данном исследовании машины, как и коммуникационная среда, сейчас не используются и считаются устаревшими, результат приведенных экспериментов наглядно показывает, что EM алгоритм хорошо параллелится, зависимость ускорения от числа узлов в кластере с небольшим количеством узлов близка к линейной, а также, что скорость работы алгоритма линейно зависит от числа объектов.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&#039;&#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;
Примеры библиотек, содержащих последовательную реализацию EM-алгоритма, или отдельных реализаций:&lt;br /&gt;
&lt;br /&gt;
# [http://docs.opencv.org/2.4/modules/ml/doc/expectation_maximization.html OpenCV(C++)] ([https://github.com/opencv/opencv/blob/master/modules/ml/src/em.cpp github])&lt;br /&gt;
# [http://www.mathworks.com/help/stats/clustering-using-gaussian-mixture-models.html Matlab]&lt;br /&gt;
# [http://scikit-learn.org/stable/modules/mixture.html Scikit learn (Python)]&lt;br /&gt;
# [http://mlpack.org/index.html MLPack(C++)]&lt;br /&gt;
&lt;br /&gt;
Примеры библиотек, содержащих параллельную реализацию EM-алгоритма, или отдельных реализаций:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Здесь приводятся как конкретные реализации, так и статьи, описывающие подходы к реализациям распараллеливания EM-алгоритма&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
# [https://spark.apache.org/ Apache Spark]&lt;br /&gt;
# [http://accord-framework.net/ Accord.NET Framework (C#)]&lt;br /&gt;
# Статья об использовании FREERIDE middleware для распараллеливания EM алгоритма &amp;lt;ref name=FREERIDE/&amp;gt; &lt;br /&gt;
# [http://andrewharp.com/gmmcuda реализация с использованием CUDA]&lt;br /&gt;
# [https://github.com/Corv/CUDA-GMM-MPI еще одна реализация с использованием CUDA]&lt;br /&gt;
# статья об использовании параллельного EM алгоритма в задачах компьютерного зрения &amp;lt;ref name=CV/&amp;gt;&lt;br /&gt;
# статья о распараллеливании EM алгоритма с использованием CUDA &amp;lt;ref name=CUDA/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Algoman</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:Noite&amp;diff=17597</id>
		<title>Обсуждение участника:Noite</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:Noite&amp;diff=17597"/>
		<updated>2016-11-16T11:16:10Z</updated>

		<summary type="html">&lt;p&gt;Algoman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Замечания к [[Участник:Noite/EM-алгоритм_кластеризации]] ==&lt;br /&gt;
&lt;br /&gt;
1) лишняя строка &amp;quot;Алгоритм кластеризации, основанный на максимизации ожидания (EM-алгоритм)&amp;quot; перед содержанием --- убрано&lt;br /&gt;
&lt;br /&gt;
2) отсутствует оценка высоты и ширины ЯПФ параллельного алгоритма во врезке в начале статьи --- врезка исправлена&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ниже - замечания второго рецензента&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
3) Во врезке так и не появилась информация по поводу параллельного алгоритма --- исправлено&lt;br /&gt;
&lt;br /&gt;
4) Из содержания нужно убрать ссылку [5] --- имеется ввиду из заголовка раздела? или подобную ссылку вообще нельзя использовать? пока ссылка перенесена из заголовка внутрь раздела&lt;br /&gt;
&lt;br /&gt;
5) В формулировке задачи в п1.1 нет разъяснения параметра m --- формулировка задачи кластеризации изменена&lt;br /&gt;
&lt;br /&gt;
6) В п1.2 парметры m, n, k почему-то превратились в M, N, K --- параметры m,n,k изменены в п1.1 и во врезке на M,N,K соответственно&lt;br /&gt;
&lt;br /&gt;
7) П 1.5. Как инициализируются скрытые переменные gamma? Выравнивание псевдокода местами нарушено. Слово &amp;quot;большУю&amp;quot; - здесь лучше использовать значок ударения --- слово большУю исправлено. Скрытые переменные могут быть инициализированы любым образом, поскольку первый E-шаг алгоритма их в любом случае перезапишет. Выравнивание псевдокода изменено.&lt;br /&gt;
&lt;br /&gt;
8) П 1.7 Информационный граф: на рисунке омега превратилась в w, гамма - в Y. --- в используемом редакторе изображений для гаммы использовался следующий символ: γ - символ гамма, взятый из википедии. То, что он похож на Y - визуальное совпадение. &lt;br /&gt;
&lt;br /&gt;
9)П 1.9 Выходные данные - сказано о векторе n. Поясните, какое значение он имеет в терминах алгоритма кластеризации. --- пояснение добавлено&lt;br /&gt;
&lt;br /&gt;
== Замечания к пункту 2.4 от 16.11.2016 == &lt;br /&gt;
&lt;br /&gt;
* текущую информацию в п 2.4 можно оставить, но для выполнения задания практикума исследование масштабируемости должно быть проведено самостоятельно&lt;/div&gt;</summary>
		<author><name>Algoman</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%95%D0%BA%D0%B0%D1%82%D0%B5%D1%80%D0%B8%D0%BD%D0%B0%D0%9A%D0%BE%D0%B7%D1%8B%D1%80%D0%B5%D0%B2%D0%B0/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%B4%D0%B8%D0%BD%D0%B0%D0%BC%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B9_%D0%B8%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B9_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_CHAMELEON&amp;diff=17596</id>
		<title>Участник:ЕкатеринаКозырева/Алгоритм динамической иерархической кластеризации CHAMELEON</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%95%D0%BA%D0%B0%D1%82%D0%B5%D1%80%D0%B8%D0%BD%D0%B0%D0%9A%D0%BE%D0%B7%D1%8B%D1%80%D0%B5%D0%B2%D0%B0/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%B4%D0%B8%D0%BD%D0%B0%D0%BC%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B9_%D0%B8%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B9_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_CHAMELEON&amp;diff=17596"/>
		<updated>2016-11-16T11:10:41Z</updated>

		<summary type="html">&lt;p&gt;Algoman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Алгоритм динамической иерархической кластеризации CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(nm + n log n + m^2 log m)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;\frac{n (n - 1)}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n+ n log(n) + m^2 log (m) + m log(m))&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;
}}&lt;br /&gt;
&lt;br /&gt;
Автор описания [[Участник:ЕкатеринаКозырева|Е.А.Козырева]]&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Алгоритм CHAMELEON был предложен в 1999 году тремя учеными из университета Миннесоты – George Karypis, Eui-Hong (Sam) Han и Vipin Kumar&amp;lt;ref&amp;gt;George Karypis, Eui-Hong (Sam) Han и Vipin Kumar, «Chameleon: Hierarchical Clustering Using Dynamic Modeling», 1999.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Предназначен для решения задач кластеризации. Кластеризация (или кластерный анализ) — это задача разбиения множества объектов на группы, называемые кластерами. Внутри каждой группы должны оказаться «похожие» объекты, а объекты разных группы должны быть как можно более отличны.&lt;br /&gt;
&lt;br /&gt;
CHAMELEON - это агломеративный иерархический алгоритм кластеризации, ключевой особенностью которого является то, что он учитывает и взаимную связность, и сходство при определении наиболее похожей пары подкластеров, основываясь на динамической модели. Это означает, что в процессе кластеризации два кластера объединяются, только если их относительная взаимная связность и относительное взаимное сходство являются высокими по отношению к внутренней взаимосвязанности кластеров и близости элементов внутри кластеров. Кроме того, CHAMELEON использует подход для моделирования степени взаимосвязанности и близости между каждой парой кластеров, который учитывает внутренние характеристики самих кластеров. Таким образом, он может автоматически адаптироваться к внутренним характеристикам объединяемых кластеров.&lt;br /&gt;
&lt;br /&gt;
CHAMELEON находит кластеры в наборе данных с помощью трехфазного алгоритма. На первой фазе происходит построение графа, путём добавления рёбер по принципу k ближайших соседей. На второй фазе CHAMELEON группирует полученные элементы в множество относительно небольших подграфов. Во время третьей фазы применяется агломеративный иерархический алгоритм кластеризации, с помощью которого находятся естесственные кластеры путем многократного объединения подграфов, полученных на прошлом этапе.&lt;br /&gt;
&lt;br /&gt;
[[File:Chameleon.png|1000px|thumb|center|Рисунок 1. Общая структура алгоритма CHAMELEON]]&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Исходные данные&#039;&#039;: &lt;br /&gt;
&lt;br /&gt;
* Множество из n точек &amp;lt;math&amp;gt;V= {v_{ij}}&amp;lt;/math&amp;gt; в метрическом пространстве, которое задано симметрической матрицей расстояний &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;n\times n&amp;lt;/math&amp;gt;.&lt;br /&gt;
* &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество ближайших соседей для вершин, &amp;lt;math&amp;gt;k \in N, k \leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
* &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; - наименьшее число вершин, которое может содержать наибольший подграф на 2-м этапе, &amp;lt;math&amp;gt;l \in N, l \leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Обозначения&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; - граф, полученный путём соединения каждой точки с её &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайшими соседями.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;K= \{K_{i}\}&amp;lt;/math&amp;gt; - разбиение множества &amp;lt;math&amp;gt;V&amp;lt;/math&amp;gt; на набор попарно непересекающихся связных подмножеств, полученное в результате выполнения второй фазы алгоритма.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;G_{2} = (K, E_{2})&amp;lt;/math&amp;gt; - взвешенный граф, вершинами которого являются получившиеся подграфы, а ребрами - количество ребер исходного графа, соединяющих соответствующие подграфы.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;C = \{C_{i}\}&amp;lt;/math&amp;gt; - итоговое разбиение множества вершин графа &amp;lt;math&amp;gt;G_{2}&amp;lt;/math&amp;gt; на набор кластеров.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Вспомогательные понятия&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Определяется как сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. Внутренняя связность &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{|EC_{(C_{i},C_{j})}|}{(|EC_{C_{i}}|+|EC_{C_{j}}|)/2}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Подсчитывается как среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Определяется как абсолютное сходство между этой парой кластеров, нормализованное с учетом их внутреннего сходства&amp;lt;ref&amp;gt;http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый этап&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
На первом этапе, согласно графо-ориентированному подходу, происходит построение графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; на матрице сходства объектов по принципу k ближайших соседей. Две вершины такого графа соединяет ребро, если объект, соответствующий любой из этих вершин попадает в число k наиболее близких объектов для объекта, соответствующего другой вершине из данной пары.&lt;br /&gt;
[[Файл:Снимок chameleon 2.png|2000px|thumb|Рисунок 2. Объекты в пространстве - слева, граф по принципу 1-го ближайшего соседа - по центру, граф по принципу 3-х ближайших соседей - справа ]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй этап&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Алгоритм разделяет полученный граф на множество сравнительно малых подграфов &amp;lt;math&amp;gt;K= \{K_{i}\}&amp;lt;/math&amp;gt;. Разделение происходит последовательно. На каждом шаге выбирается подграф, содержащий наибольшее число вершин. Этот граф разделяется на два подграфа так, что разделитель ребер графа минимален и каждый из получаемых подграфов содержит не менее 25 % вершин исходного графа. Процесс разделения останавливается, когда наибольший подграф содержит меньше некоторого заданного числа вершин. Обычно величина этого параметра задается равной значению от 1 до 5 % от числа объектов. Полученное множество связных графов считается множеством начальных кластеров, на котором требуется провести последовательное иерархическое объединение.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Третий этап&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Третий этап заключается в итеративном преобразовании множества подграфов &amp;lt;math&amp;gt;K= \{K_{i}\}&amp;lt;/math&amp;gt; в множество кластеров &amp;lt;math&amp;gt;C = \{C_{i}\}&amp;lt;/math&amp;gt;. Алгоритм осуществляет агломеративную иерархическую кластеризацию на основании показателей &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Существует две стратегии анализа показателей сходства. Первая подразумевает наличие некоторых пороговых значений &amp;lt;math&amp;gt;T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;T_{RC}&amp;lt;/math&amp;gt;. В соответствии с этой стратегией, алгоритм для каждого кластера &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; проверяет, отвечают ли смежные (наиболее близкие) ему кластеры условиям:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} \geqslant T_{RI}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} \geqslant T_{RC}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если более одного смежного кластера отвечает этим условиям, то алгоритм выбирает для объединения наиболее связный кластер (граф), то есть такой кластер &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;, с которым у кластера &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; получается наибольшая абсолютная взаимная связность. По завершению прохода по всем кластерам, созданные таким образом пары объединяются. Параметры &amp;lt;math&amp;gt;T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;T_{RC}&amp;lt;/math&amp;gt; могут использоваться для изменения характеристик получаемых кластеров.&lt;br /&gt;
&lt;br /&gt;
Вторая стратегия заключается в использовании специальной функции, объединяющей понятия относительной взаимной связности и относительного взаимного сходства. На каждом шаге выбираются те кластеры для объединения, которые максимизируют эту функцию:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; выбирается пользователем. Если &amp;lt;math&amp;gt;\alpha &amp;gt; 1 &amp;lt;/math&amp;gt;, то алгоритм придает большее значение относительному взаимному сходству, а если &amp;lt;math&amp;gt;\alpha &amp;lt;  1 &amp;lt;/math&amp;gt;, то большее значение имеет относительная взаимная связность.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Вычисляемые данные&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;U = (u_1, u_2, ..., u_n)&amp;lt;/math&amp;gt; - n-мерный вектор, где &amp;lt;math&amp;gt;u_i \in N_{[C]}&amp;lt;/math&amp;gt; - порядковый номер кластера, к которому принадлежит вершина i исходного множества V.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм имеет три вычислительных ядра, по одному на каждый этап.&lt;br /&gt;
&lt;br /&gt;
На первом этапе вычислительным ядром является процесс нахождения &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей для каждой вершины, который заключается в анализе матрицы расстояний.&lt;br /&gt;
&lt;br /&gt;
На втором этапе вычислительным ядром является процесс поиска подходящего разбиения очередного подграфа на два графа с минимизацией разделителя ребер графа.&lt;br /&gt;
&lt;br /&gt;
На третьем этапе вычислительным ядром является расчет величин &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; для каждой пары смежных кластеров.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Как уже рассказывалось ранее, алгоритм включает в себя три основных этапа, каждый из которых, по сути, является отдельным алгоритмом. Этапы выполняются последовательно относительно друг друга. &lt;br /&gt;
&lt;br /&gt;
Макрооперация на первом этапе - процедура нахождения &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей, на втором - процедура разбиения наибольшего подграфа на два графа, на третьем - процедура вычисления показателей сходства, на основе которых принимается решение о слиянии подграфов в кластер.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый этап&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
 int n; //количество вершин&lt;br /&gt;
 int k; //количество соседей&lt;br /&gt;
 int A[n][n] //матрица расстояний&lt;br /&gt;
 int D[k] //массив вершин-соседей&lt;br /&gt;
 int E[n][n] //матрица ребер графа &amp;lt;math&amp;gt;G_{2} = (K, E_{2})&amp;lt;/math&amp;gt;&lt;br /&gt;
 for i=1 to n-1 do&lt;br /&gt;
     {&lt;br /&gt;
       for j=i+1 to n do &lt;br /&gt;
            {&lt;br /&gt;
               //заполняем массив вершин-соседей вставляя новые вершины, если они ближе, чем самая далекая из массива. &lt;br /&gt;
            }&lt;br /&gt;
       for j=0 to k do &lt;br /&gt;
            {&lt;br /&gt;
               //для каждой вершины соседа заполняем соответствующую ячейку из матрицы E[n][n] единицей&lt;br /&gt;
            }&lt;br /&gt;
   &lt;br /&gt;
     }&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй этап&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 1. Все связные подграфы в отсортированном порядке помещаются в список;&lt;br /&gt;
 2. Берем наибольший элемент списка, вычисляем количество его вершин. Если число вершин &amp;gt; l, то идем в пункт 3. Иначе в пункт 5;&lt;br /&gt;
 3. Разбиваем подграф на два подграфа таким образом, чтобы разделитель ребер графа был минимален и каждый из получаемых подграфов содержал не менее 25 % вершин исходного графа;&lt;br /&gt;
 4. Добавляем полученные элементы в список подграфов таким образом, чтобы список оставался отсортированным. Идем в пункт 2;&lt;br /&gt;
 5. Нашли искомое множество подграфов math&amp;gt;K = \{K_{i}\}&amp;lt;/math&amp;gt;;&lt;br /&gt;
 6. Создаем и заполняем матрицу матрицу расстояний для графа &amp;lt;math&amp;gt;G_{2} = (K, E_{2})&amp;lt;/math&amp;gt;. Получаем искомый набор рёбер &amp;lt;math&amp;gt;E_{2}&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;
 1. Заводим два массива: а) массив кластеров C, полученных на предыдущем этапе, б) массив объединений кластеров F, которые мы будем получать на этом этапе;&lt;br /&gt;
 2. Берем следующий кластер &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; (на первом шаге - первый). Если все кластеры просмотрены, идем в пункт 6;&lt;br /&gt;
 3. Берем следующий кластер &amp;lt;math&amp;gt;C_{j}, i&amp;lt;&amp;gt;j&amp;lt;/math&amp;gt;. Если все кластеры просмотрены, то идем в пункт 2;&lt;br /&gt;
 4. Проверяем смежность &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;. Если не смежны, то возвращаемся в пункт 3. Если смежны, идем в пункт 5;&lt;br /&gt;
 5. Рассчитываем показатели &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Проверяем, удовлетворяют ли найденные значения условиям:&lt;br /&gt;
 *&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} \geqslant T_{RI}&amp;lt;/math&amp;gt;&lt;br /&gt;
 *&amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} \geqslant T_{RC}&amp;lt;/math&amp;gt;&lt;br /&gt;
 Если нет, то идем в пункт 3. Иначе если смежность пары кластеров выше, чем у предыдущих найденных, то &amp;lt;math&amp;gt;F_{i}=j&amp;lt;/math&amp;gt;. Идем в пункт 3;&lt;br /&gt;
 6. Если в списке F есть хотя бы одна пара кластеров для слияния, то выполняем слияние, обновляем массив кластеров и массив объединений кластеров. Идем в пункт 2.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
1) Для построения графа на основе метода k ближайших соседей для n вершин требуется &amp;lt;math&amp;gt;O(n log(n))&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;J.H. Friedman, J.L. Bentley, and R.A. Finkel. An algorithm for ﬁnding best matches in logarithmic expected time. ACM Transactions on Mathematical Software, 3:209–226, 1977.&amp;lt;/ref&amp;gt;; для наборов данных большой размерности эта величина составляет &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;S. Berchtold, C. Bohm, D. Keim, and H.-P. Kriegel. Cost model for nearest neighbor search in high dimensional data space. In Proc. of Symposium on Principles of Database Systems, Tucson, Arizona, 1997.&amp;lt;/ref&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
2) Для выделения множества сравнительно малых связных подграфов требуется &amp;lt;math&amp;gt;nm&amp;lt;/math&amp;gt; операций, где &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - количество подграфов, полученных на втором этапе алгоритма;&lt;br /&gt;
&lt;br /&gt;
3) Формирование набора кластеров, на основе множества подграфов, полученных на предыдущем этапе, требует &amp;lt;math&amp;gt;m^2log(m)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Итого, для n вершин получаем последовательную сложность &amp;lt;math&amp;gt;O(n log(n)+nm+m^2log(m))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
[[File:СК.png]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Первый этап работы алгоритма можно распределить между &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; процессами. На вход каждому процессу подается своя вершина, далее происходит процедура поиска &amp;lt;math&amp;gt;k&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;
&lt;br /&gt;
Второй этап распараллеливается путем подачи на вход свободному процессу очередного подграфа для разделения. Число итераций оценивается в &amp;lt;math&amp;gt;O(n log(n))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Третий этап делится на расчет показателей схожести и соединение подграфов в кластеры. Процесс расчета показателей можно распараллелить, подавая каждому процессу на вход пару подграфов. Сложность этого процесса оценивается как &amp;lt;math&amp;gt;m log(m)&amp;lt;/math&amp;gt;. Соединение подграфов в кластеры выполняется последовательно, сложность процесса составляет &amp;lt;math&amp;gt;m^2 log(m)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Таким образом получаем общую параллельную сложность алгоритма: &amp;lt;math&amp;gt;O(n+ n log(n) + m^2 log (m) + m log(m))&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;
1. Симметрическая матрица &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; расстояний между элементами данных размера &amp;lt;math&amp;gt;n\times n&amp;lt;/math&amp;gt; с нулями на главной диагонали  (&amp;lt;math&amp;gt;a_{ii}= 0, i = 1, \ldots, N&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
2. &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество ближайших соседей для вершин (рекомендуемое значение &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; от 5 до 20 в зависимости от количества анализируемых объектов).&lt;br /&gt;
&lt;br /&gt;
3. &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; - наименьшее число вершин, которое может содержать наибольший подкластер на 2-м этапе . Величина этого параметра варьируется от 1 до 5 % от общего числа объектов.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\frac{n (n - 1)}{2}&amp;lt;/math&amp;gt; (в силу симметричности и нулевой главной диагонали достаточно хранить только  над/поддиагональные элементы).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Вектор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; чисел &amp;lt;math&amp;gt;u_{1}, u_{2}, \ldots, u_{N}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;u_{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;Объём выходных данных&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&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; для больших наборов данных и логарифмическим для n вершин. На втором этапе сложно оценить это соотношение - оно сильно зависит от параметров &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt;. На третьем этапе соотношение равно &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Оценка &#039;&#039;вычислительной мощности&#039;&#039; выглядит следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;                  для 1-го этапа;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O(\frac{nm}{n^2+m^2})&amp;lt;/math&amp;gt;   для 2-го этапа;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O(\frac{m^2log(m)}{m^2+n})&amp;lt;/math&amp;gt; для 3-го этапа;&lt;br /&gt;
&lt;br /&gt;
Алгоритм является &#039;&#039;недетерминированным&#039;&#039;. Хотя 1-й этап детерминирован, на 2-ом этапе могут быть найдены различные разбиения на подграфы, что повлияет и на итоговый результат работы алгоритма.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
см. позднее&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Последовательная реализация алгоритма доступна по ссылке &amp;lt;ref&amp;gt;http://read.pudn.com/downloads36/sourcecode/math/115779/chameleon/chameleon.c__.htm&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
CHAMELEON можно реализовать с использованием графовых библиотек METIS &amp;lt;ref&amp;gt;http://glaros.dtc.umn.edu/gkhome/metis/metis/overview&lt;br /&gt;
&amp;lt;/ref&amp;gt;, hMETIS &amp;lt;ref&amp;gt;http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview&amp;lt;/ref&amp;gt; и RANN &amp;lt;ref&amp;gt;https://cran.r-project.org/web/packages/RANN/index.html&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь &amp;lt;ref&amp;gt;http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON не найдено.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Algoman</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%90%D1%80%D1%82%D0%B5%D0%BC_%D0%A2%D0%B0%D1%80%D0%B0%D0%BD/%D0%93%D1%80%D0%B0%D1%84%D0%BE-%D0%BE%D1%80%D0%B8%D0%B5%D0%BD%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_CHAMELEON&amp;diff=17595</id>
		<title>Участник:Артем Таран/Графо-ориентированный алгоритм кластеризации CHAMELEON</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%90%D1%80%D1%82%D0%B5%D0%BC_%D0%A2%D0%B0%D1%80%D0%B0%D0%BD/%D0%93%D1%80%D0%B0%D1%84%D0%BE-%D0%BE%D1%80%D0%B8%D0%B5%D0%BD%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_CHAMELEON&amp;diff=17595"/>
		<updated>2016-11-16T11:10:26Z</updated>

		<summary type="html">&lt;p&gt;Algoman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = Графо-ориентированный алгоритм кластеризации CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n^2+nm+m^2log(m))&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n + log(n) + mlog(m) + m^2log(m))&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;\frac{n (n - 1)}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Статью подготовили: [[Участник:Артем_Таран|Артём Таран Иванович]] (разделы 1.1 - 1.10, 2.7), [[Участник:ShimchikN|Шимчик Никита Владимирович]] (разделы 1.1 - 1.10, 2.7).&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Кластеризация — многомерная статистическая процедура, выполняющая сбор данных, содержащих информацию о выборке объектов, и затем упорядочивающая объекты в сравнительно однородные группы (кластеры) с минимизацией межкластерного сходства и максимизацией внутрикластерного сходства.&lt;br /&gt;
&lt;br /&gt;
Графо-ориентированный алгоритм кластеризации CHAMELEON&amp;lt;ref name=&amp;quot;rt&amp;quot;&amp;gt;http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf&amp;lt;/ref&amp;gt; - алгоритм, который измеряет сходство двух кластеров на основе&lt;br /&gt;
динамической модели. В процессе кластеризации два кластера объединяются, только если показатели взаимосвязанности и близости между двумя кластерами являются высокими по отношению к показателям внутренней взаимосвязанности кластеров и близости элементов внутри этих кластеров. Процесс слияния с использованием динамической модели, использующийся в данном алгоритме облегчает открытие&lt;br /&gt;
природных и однородных кластеров. Методология динамического моделирования кластеров, использующаяся в CHAMELEON,&lt;br /&gt;
применима ко всем типам данных, для которых может быть построена матрица подобия.&lt;br /&gt;
&lt;br /&gt;
Алгоритм кластеризации CHAMELEON включает в себя три этапа:&lt;br /&gt;
&lt;br /&gt;
1) Построение графа, путём добавления рёбер по принципу k ближайших соседей.&lt;br /&gt;
&lt;br /&gt;
2) Выделение множества сравнительно малых связных подграфов.&lt;br /&gt;
&lt;br /&gt;
3) Формирование набора кластеров, на основе множества подграфов, полученных на предыдущем этапе.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Графы k ближайших соседей.jpg|1000px|thumb|center|Графы k ближайших соседей: 1) объекты в пространстве, 2) граф по принципу 1-го ближайшего соседа, 3) граф по принципу 2-го ближайшего соседа, 4) граф по принципу 3-х ближайших соседей&amp;lt;ref name=&amp;quot;rt&amp;quot;&amp;gt;http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf&amp;lt;/ref&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
==== Данные ====&lt;br /&gt;
* &#039;&#039;&#039;Исходные данные&#039;&#039;&#039;: множество из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; точек &amp;lt;math&amp;gt;V = \{v_{i}\}&amp;lt;/math&amp;gt; в метрическом пространстве, которое может быть задано в виде треугольной матрицы расстояний &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;n\times n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Промежуточный результат после первого этапа&#039;&#039;&#039;: граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, полученный путём соединения каждой точки с её &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайшими соседями.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Промежуточный результат после второго этапа&#039;&#039;&#039;: разбиение множества &amp;lt;math&amp;gt;V&amp;lt;/math&amp;gt; на набор &amp;lt;math&amp;gt;K = \{K_{i}\}&amp;lt;/math&amp;gt; попарно непересекающихся связных подмножеств, из которого образуется взвешенный граф &amp;lt;math&amp;gt;G_{2} = (K, E_{2})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Промежуточный результат после третьего этапа&#039;&#039;&#039;: итоговое разбиение множества вершин графа &amp;lt;math&amp;gt;G_{2}&amp;lt;/math&amp;gt; на набор кластеров &amp;lt;math&amp;gt;C = \{C_{i}\}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Вычисляемые данные&#039;&#039;&#039;: n-мерный вектор &amp;lt;math&amp;gt;v&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt;), показывающий отображение исходного множества точек на набор кластеров &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Определения ====&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Абсолютная взаимная связность между парой кластеров &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;&#039;&#039; определяется как сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; с вершинами из &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;. Эти ребра, фактически, входят в разделитель ребер графа, состоящего из кластеров &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;, и разбивающим его на подграфы &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;. Обозначается эта величина как&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Внутреннюю связность &amp;lt;math&amp;gt;EC_{C_{i}}&amp;lt;/math&amp;gt; кластера &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; можно вычислить как сумму ребер, входящих в разделитель ребер, разбивающий &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; на два совершенно равных подграфа.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Относительная взаимная &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; связность  пары кластеров &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;&#039;&#039; определяется формулой:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Учитывая значения относительной взаимной связности, можно добиться получения кластеров разного размера, формы и плотности, то есть общего внутреннего сходства.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Абсолютное взаимное сходство между парой кластеров &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;&#039;&#039; подсчитывается как среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; соответственно. Эти соединения обусловлены предыдущим разбиением общего графа, полученного на матрице сходства.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Относительное взаимное сходство &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; между парой кластеров &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;&#039;&#039; определяется как абсолютное сходство между этой парой кластеров, нормализованное с учетом их внутреннего сходства и вычисляется по формуле:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;S_{EC_{(C_{i})}}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;S_{EC_{(C_{i})}}&amp;lt;/math&amp;gt; - средние веса ребер (значения сходства), принадлежащих разделителю ребер кластеров &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; соответственно,&lt;br /&gt;
и &amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - средний вес ребер, соединяющих вершины &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; с вершинами &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;, причем ребра принадлежат разделителю ребер &amp;lt;math&amp;gt;EC_{(C_{i})}&amp;lt;/math&amp;gt;, определенному ранее.&lt;br /&gt;
&lt;br /&gt;
Далее, алгоритм применяет агломеративную иерархическую кластеризацию с использованием вышеозначенных показателей. Причем существует две стратегии их учета. Первая подразумевает наличие некоторых пороговых значений &amp;lt;math&amp;gt;T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;T_{RC}&amp;lt;/math&amp;gt;. В соответствии с этой стратегией, алгоритм для каждого кластера &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; проверяет, отвечают ли смежные (наиболее близкие) ему кластеры условиям:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} \geqslant T_{RI}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} \geqslant T_{RC}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если более одного смежного кластера отвечает этим условиям, то алгоритм выбирает для объединения наиболее связный кластер (граф), то есть такой кластер &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;, с которым у кластера &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; получается наибольшая абсолютная взаимная связность. По завершению прохода по всем кластерам, созданные таким образом пары объединяются. Параметры &amp;lt;math&amp;gt;T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;T_{RC}&amp;lt;/math&amp;gt; могут использоваться для изменения характеристик получаемых кластеров.&lt;br /&gt;
&lt;br /&gt;
Вторая стратегия заключается в использовании специальной функции, объединяющей понятия относительной взаимной связности и относительного взаимного сходства. На каждом шаге выбираются те кластеры для объединения, которые максимизируют эту функцию:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; выбирается пользователем. Если &amp;lt;math&amp;gt;\alpha &amp;gt; 1 &amp;lt;/math&amp;gt;, то алгоритм придает большее значение относительному взаимному сходству, а если &amp;lt;math&amp;gt;\alpha &amp;lt;  1 &amp;lt;/math&amp;gt;, то большее значение имеет относительная взаимная связность. Разумеется, данный подход позволяет получить полную дендрограмму кластерного анализа&amp;lt;ref name=&amp;quot;rty&amp;quot;&amp;gt;http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
&lt;br /&gt;
На первом этапе работы алгоритма вычислительным ядром можно считать процесс нахождения k ближайших соседей для каждой отдельной вершины.&lt;br /&gt;
&lt;br /&gt;
На втором этапе работы алгоритма вычислительным ядром является поиск разбиения графа на два подграфа с минимизацией разделителя рёбер графа.&lt;br /&gt;
&lt;br /&gt;
На третьем этапе работы алгоритма вычислительным ядром является расчёт &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; для пары смежных кластеров, а также их слияние.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап соответствует отдельному алгоритму. &lt;br /&gt;
&lt;br /&gt;
* Макрооперацией на первом этапе является процедура выделения k ближайших соседей.&lt;br /&gt;
&lt;br /&gt;
* Макрооперацией на втором этапе является процедура разбиения наибольшего подграфа на каждой итерации.&lt;br /&gt;
&lt;br /&gt;
* Макрооперациями на третьем этапе являются процедуры вычисления метрики для принятия решения об объединении кластеров и объединение кластеров на каждой итерации.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
* Первый этап (псевдокод):&lt;br /&gt;
  integer n; // Количество точек.&lt;br /&gt;
  integer k; // Параметр k&lt;br /&gt;
  integer A[n][n]; // Верхняя треугольная матрица расстояний между точками.&lt;br /&gt;
  &lt;br /&gt;
  integer E[n][n]; // Верхняя треугольная матрица рёбер графа G - изначально инициализирована нулями.&lt;br /&gt;
  foreach (integer i in (1,n-1) ) {&lt;br /&gt;
    integer Neighbors[k]; // матрица, используемая хранения ближайших соседей&lt;br /&gt;
    integer countN = 0;&lt;br /&gt;
    &lt;br /&gt;
    foreach (integer j in (i+1, n) ) {&lt;br /&gt;
      // Заполняем матрицу Neighbors, добавляя новые элементы и увеличивая счётчик countN.&lt;br /&gt;
      // Когда countN станет равен k, новые элементы будут вставляться на место старых, либо отбрасываться.&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    foreach (integer j in (0, countN) ) {&lt;br /&gt;
      E[min(i,j), max(i,j)] = 1;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  return E;&lt;br /&gt;
&lt;br /&gt;
* Второй этап:&lt;br /&gt;
  [[File:Диаграмма_шаг_2.png]]&lt;br /&gt;
&lt;br /&gt;
* Третий этап:&lt;br /&gt;
  [[File:Chameleon_stage_3.png|611px]]&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
1) Построение графа на основе метода k ближайших соседей в худшем случае требует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций;&lt;br /&gt;
&lt;br /&gt;
2) Для выделения множества сравнительно малых связных подграфов требуется &amp;lt;math&amp;gt;nm&amp;lt;/math&amp;gt; операций;&lt;br /&gt;
&lt;br /&gt;
3) Формирование набора кластеров, на основе множества подграфов, полученных на предыдущем этапе, требует &amp;lt;math&amp;gt;m^2log(m)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Итого, получаем последовательную сложность &amp;lt;math&amp;gt;O(n^2+nm+m^2log(m))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
&lt;br /&gt;
  [[File:Chameleon_inforgraph.png|811px]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Первый этап работы алгоритма можно распределить между &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; процессами: в этом случае каждому процессу назначается своя точка и происходит поиск &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей. Таким образом, его параллельная сложность составляет &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
На втором этапе количество задействованных процессов может варьироваться в зависимости от входных данных. В худшем случае число итераций можно оценить как &amp;lt;math&amp;gt;O(log(n))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
На третьем этапе можно распараллелить процесс расчёта метрик сходства между кластерами, однако итоговое слияние всё равно должно выполняться последовательно.&lt;br /&gt;
Поскольку процесс сравнения кластеров возможно распараллелить, сложность 3-го этапа составляет &amp;lt;math&amp;gt;mlog(m) + m^2log(m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Таким образом, суммарная параллельная сложность оказывается равна &amp;lt;math&amp;gt;O(n + log(n) + mlog(m) + m^2log(m))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
* Входные данные: &lt;br /&gt;
&lt;br /&gt;
1) Треугольная матрица &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;n\times n&amp;lt;/math&amp;gt; (где n — количество объектов), в которой элементу &amp;lt;math&amp;gt;a_{ij}&amp;lt;/math&amp;gt; соответствует расстояние между i-м и j-м объектами.&lt;br /&gt;
&lt;br /&gt;
2) Количество ближайших соседей &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; для вершин (рекомендуемое значение &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; от 5 до 20 в зависимости от количества анализируемых объектов).&lt;br /&gt;
&lt;br /&gt;
3) Наименьшее число вершин, которое может содержать наибольший подграф на 2-м этапе &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt;. Величина этого параметра варьируется от 1 до 5 % от общего числа объектов.&lt;br /&gt;
&lt;br /&gt;
* Объём входных данных: &amp;lt;math&amp;gt;\frac{n (n - 1)}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Выходные данные: n-мерный вектор &amp;lt;math&amp;gt;v&amp;lt;/math&amp;gt;, в котором элементу &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; соответствует номер кластера, присвоенный i-му объекту&lt;br /&gt;
&lt;br /&gt;
* Объём выходных данных: &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Первый этап алгоритма обладает хорошим ресурсом параллелизма: параллельная сложность его выполнения составляет &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;, что намного лучше последовательной оценки &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
У второго и третьего этапов алгоритма сложно полностью оценить ресурсы параллелизма. Но оба этапа возможно частично распараллелить.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вычислительную мощность&#039;&#039;&#039; для разных этапов алгоритма можно оценить как:&lt;br /&gt;
&lt;br /&gt;
1 этап: &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2 этап: &amp;lt;math&amp;gt;O(\frac{nm}{n^2+m^2})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3 этап: &amp;lt;math&amp;gt;O(\frac{m^2log(m)}{m^2+n})&amp;lt;/math&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью данного алгоритма является его недетерминированность. Несмотря на то, что 1-й этап детерминирован, алгоритм в целом является недетерминированным, так как на 2-ом этапе могут быть найдены различные разбиения на подграфы, а это повлияет и на итоговый результат работы алгоритма.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Существует несколько последовательных реализаций алгоритма. С одной из них можно ознакомиться по ссылке &amp;lt;ref name=&amp;quot;tra&amp;quot;&amp;gt;http://www.codeforge.com/article/192925&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, как, например METIS &amp;lt;ref name=&amp;quot;tru&amp;quot;&amp;gt;http://glaros.dtc.umn.edu/gkhome/metis/metis/overview&amp;lt;/ref&amp;gt; , hMETIS &amp;lt;ref name=&amp;quot;tri&amp;quot;&amp;gt;http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview&amp;lt;/ref&amp;gt; и RANN &amp;lt;ref name=&amp;quot;tro&amp;quot;&amp;gt;https://cran.r-project.org/web/packages/RANN/index.html&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь &amp;lt;ref name=&amp;quot;tr&amp;quot;&amp;gt;http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;/div&gt;</summary>
		<author><name>Algoman</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:Steve/%D0%93%D1%80%D0%B0%D1%84%D0%BE-%D0%BE%D1%80%D0%B8%D0%B5%D0%BD%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_CHAMELEON&amp;diff=17594</id>
		<title>Участник:Steve/Графо-ориентированный алгоритм кластеризации CHAMELEON</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:Steve/%D0%93%D1%80%D0%B0%D1%84%D0%BE-%D0%BE%D1%80%D0%B8%D0%B5%D0%BD%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_CHAMELEON&amp;diff=17594"/>
		<updated>2016-11-16T11:10:04Z</updated>

		<summary type="html">&lt;p&gt;Algoman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Авторы: Кириллов Валентин Владимирович: 1.1, 1.3, 1.4, 1.7, 1.9, 1.10, 2.7;&lt;br /&gt;
Холопкин Степан Андреевич: 1.2, 1.5, 1.6, 1.7, 1.8, 1.10&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Графо-ориентированный алгоритм кластеризации CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n^2+nm+n log n + m^2 log(m))&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(log(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;n&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &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;
== Общее описание алгоритма ==&lt;br /&gt;
Алгоритм CHAMELEON первые представлен в 1999 департаментом компьютерных наук и инженерии, университет Миннесоты, США. Авторы George Karypis, Eui-Hong (Sam) Han, Vipin Kumar&amp;lt;ref&amp;gt;CHAMELEON: A Hierarchical Clustering Algorithm Using Dynamic Modeling George Karypis Eui-Hong (Sam) Han Vipin Kumar Department of Computer Science and Engineering University of Minnesota 4-192 EECS Bldg., 200 Union St. SE Minneapolis, MN 55455, USA Technical Report #99–007 {karypis,han,kumar}@cs.umn.edu &amp;lt;/ref&amp;gt; &amp;lt;ref&amp;gt; ЭКСПЕРИМЕНТАЛЬНЫЕ РЕЗУЛЬТАТЫ ИССЛЕДОВАНИЯ КАЧЕСТВА КЛАСТЕРИЗАЦИИ РАЗНООБРАЗНЫХ НАБОРОВ ДАННЫХ С ПОМОЩЬЮ МОДИФИЦИРОВАННОГО АЛГОРИТМА ХАМЕЛЕОН © Т. Б. Шатовская, А. А. Заремская &amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Кластеризация – процесс разбиения множества данных по некоторому признаку на такие группы, что в пределах одной группы данные максимально схожи по данному признаку, а в разных группах данные максимально различны. Иерархические алгоритмы кластеризации строят не одно разбиение множества данных на кластеры, а систему вложенных разбиений.  CHAMELEON является агломеративным методом (снизу вверх), когда после первого разбиения на мелкие кластеры пары близлежащих кластеров итеративно объединяются в общий кластер. На первом этапе CHAMELEON использует алгоритм разделения графа для получения набора относительно малых кластеров. На втором этапе, для объединения кластеров, полученных на первом этапе, в настоящие кластеры, используется иерархическая агломеративная кластеризация. Таким образом, алгоритм, фактически, является гибридным, построенным комбинацией графо-ориентированных и классических иерархических методов.&lt;br /&gt;
&lt;br /&gt;
На первом этапе, согласно графо-ориентированному подходу, происходит построение графа на матрице сходства объектов по принципу k ближайших соседей. Две вершины такого графа соединяет ребро, если объект, соответствующий любой из этих вершин попадает в число k наиболее близких объектов для объекта, соответствующего другой вершине из данной пары.&lt;br /&gt;
[[Файл:Cham1.jpg ]][[Файл:Cham2.jpg ]][[Файл:Cham3.jpg ]]&lt;br /&gt;
&lt;br /&gt;
На рисунке изображены: объекты в пространстве – слева, граф по принципу 1-го ближайшего соседа – в середине, граф по принципу 3-х ближайших соседей – справа &amp;lt;ref&amp;gt; International Journal of Computer Applications (0975 – 8887) Volume 79 – No8, October 2013 11 Parallel Algorithm for the Chameleon Clustering Algorithm using Dynamic Modeling &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;
[[Файл:Scheme_algo.jpg | thumb | center | 1000px | CHAMELEON: A Hierarchical Clustering Algorithm Using Dynamic Modeling]]&lt;br /&gt;
&lt;br /&gt;
На рисунке представлена схема работы алгоритма CHAMELEON.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&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) Представление набора данных в виде &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; с помощью алгоритма &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ближайших соседей: &amp;lt;math&amp;gt;e = (v_i, v_j) \in E&amp;lt;/math&amp;gt;, если &amp;lt;math&amp;gt;dist(v_i, v_j) \in sorted(\{r | r = dist(v_i, v_k), k = 1,...,n\})[1..k]&amp;lt;/math&amp;gt;, причем &amp;lt;math&amp;gt;weight(e) = dist(v_i, v_j)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2) Разбиение графа на небольшие кластеры. Для этого необходимо создать множество &amp;lt;math&amp;gt;C = G&amp;lt;/math&amp;gt; и выполнять цикл со следующими шагами на каждой его итерации:&lt;br /&gt;
&lt;br /&gt;
* Найдем &amp;lt;math&amp;gt;C_{greatest}&amp;lt;/math&amp;gt; такой, что &amp;lt;math&amp;gt;|C_{greatest}| = \max_{1 \leq j \leq |C|}|C_j|&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Если &amp;lt;math&amp;gt;\frac{|C_{greatest}|}{|V|} &amp;gt; MINSIZE&amp;lt;/math&amp;gt;, то разделить &amp;lt;math&amp;gt;C_{greatest}&amp;lt;/math&amp;gt; на 2 кластера &amp;lt;math&amp;gt;C_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_2&amp;lt;/math&amp;gt;, удалить &amp;lt;math&amp;gt;C_{greatest}&amp;lt;/math&amp;gt; из &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;, и добавить &amp;lt;math&amp;gt;C_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_2&amp;lt;/math&amp;gt; в &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* В противном случае завершил цикл.&lt;br /&gt;
&lt;br /&gt;
3) Создать начальный набор кластеров &amp;lt;math&amp;gt;C_{current} = C&amp;lt;/math&amp;gt;. Затем выполнять цикл со следующими шагами на каждой итерации:&lt;br /&gt;
&lt;br /&gt;
* Для каждой пары кластеров &amp;lt;math&amp;gt;C_i, C_j \in C_{current}&amp;lt;/math&amp;gt; вычислить следующие показатели:&lt;br /&gt;
** &amp;lt;math&amp;gt;EC(C_i, C_j) = \sum_{e \in conn(C_i, C_j)}weight(e)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;conn(C_i, C_j) = \{(v, w) | v \in C_i, w \in C_j\}&amp;lt;/math&amp;gt;&lt;br /&gt;
** &amp;lt;math&amp;gt;EC(C_i) = \sum_{e \in mincut(C_i)}weight(e)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;mincut(C_i)&amp;lt;/math&amp;gt; - минимальный разрез &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt;. Аналогичным образом вычислить &amp;lt;math&amp;gt;EC(C_j)&amp;lt;/math&amp;gt;.&lt;br /&gt;
** &amp;lt;math&amp;gt;\bar{S}_{EC(C_i, C_j)} = \frac{EC(C_i, C_j)}{|conn(C_i, C_j)|} &amp;lt;/math&amp;gt;&lt;br /&gt;
** &amp;lt;math&amp;gt;\bar{s}_{EC(C_i)} = \frac{EC(C_i)}{|mincut(C_i)|}&amp;lt;/math&amp;gt;&lt;br /&gt;
* Вычислить относительную взаимную связность и относительное взаимное сходство двух текущих кластеров:&lt;br /&gt;
** &amp;lt;math&amp;gt;RI(C_i, C_j) = \frac{|EC(C_i,C_j)|}{\frac{|EC(C_i)| + |EC(C_j)|}{2}}&amp;lt;/math&amp;gt;&lt;br /&gt;
** &amp;lt;math&amp;gt;RC(C_i, C_j) = \frac{\bar{S}_{EC(C_i,C_j)}}{\frac{|C_i|}{|C_i|+|C_j|}\bar{S}_{EC(C_i)} + \frac{|C_j|}{|C_i|+|C_j|}\bar{S}_{EC(C_j)}}&amp;lt;/math&amp;gt;&lt;br /&gt;
* Если &amp;lt;math&amp;gt;RI(C_i, C_j)^\alpha RC(C_i, C_j) &amp;gt; t&amp;lt;/math&amp;gt;, то слить данную пару кластеров, иначе - перейти к следующей паре. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - параметр, с помощью которого можно выбирать, какой из показателей важнее - относительная взаимная связность или относительное взаимное сходство, а &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - параметр, показывающий самый нижний уровень сходства кластеров, при котором их можно слить.&lt;br /&gt;
* Если на какой-то итерации цикла ни одна пара кластеров не была слита, то завершить цикл.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Из математического описания алгоритма следует, что вычислительное ядро алгоритма сосредоточено в вычислении относительной взаимной связности и относительного взаимного сходства каждой пары кластеров на каждой итерации алгоритма.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;RI(C_i, C_j) = \frac{|EC(C_i,C_j)|}{\frac{|EC(C_i)| + |EC(C_j)|}{2}}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;RC(C_i, C_j) = \frac{\bar{S}_{EC(C_i,C_j)}}{\frac{|C_i|}{|C_i|+|C_j|}\bar{S}_{EC(C_i)} + \frac{|C_j|}{|C_i|+|C_j|}\bar{S}_{EC(C_j)}}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
В первой части первого этапа алгоритма применяется алгоритм построения графа методом k ближайших соседей. &lt;br /&gt;
&lt;br /&gt;
Во второй части первого этапа алгоритма при разбиении кластера на два подкластера применяется алгоритм пакета METIS от Karypis Lab.&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;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
 // параметры&lt;br /&gt;
 // число ближайших соседей в первой фазе алгоритма&lt;br /&gt;
 int k;&lt;br /&gt;
 // минимальный относительный размер каждого из начальных кластеров&lt;br /&gt;
 double MINSIZE;&lt;br /&gt;
 // параметры, определяющий, что важнее в определении похожести&lt;br /&gt;
 // двух кластеров - относительная взаимосвязанность&lt;br /&gt;
 // или относительная близость&lt;br /&gt;
 int alpha;&lt;br /&gt;
 // порог, определяющий минимальную похожесть кластеров, необходимую&lt;br /&gt;
 // для их слияния&lt;br /&gt;
 int threshold;&lt;br /&gt;
 int n = number_of_vertices;&lt;br /&gt;
 double graph_matrix[n][n] = {0};&lt;br /&gt;
 // фаза 1 - для каждой вершины найдем k ближайших к ней и соединим &lt;br /&gt;
 // получившиеся наборы ребрами&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; i++) {&lt;br /&gt;
 	double k_nearest_indices[k] = findKNearest(i);&lt;br /&gt;
 	for (int near_ind = 0; near_ind &amp;lt; k; near_ind++) {&lt;br /&gt;
 		connect(i, near_ind);&lt;br /&gt;
 	}&lt;br /&gt;
 }&lt;br /&gt;
 // фаза 2 - осуществление начального разбиения на кластеры&lt;br /&gt;
 Cluster initial_clusters[] = all(graph_matrix);&lt;br /&gt;
 while (1) {&lt;br /&gt;
 	Cluster greatest = getGreatestCluster(initial_clusters);&lt;br /&gt;
 	if (greatest.size() / n &amp;lt; MINSIZE) {&lt;br /&gt;
 		break;&lt;br /&gt;
 	} then {&lt;br /&gt;
 		Cluster c1;&lt;br /&gt;
 		Cluster c2;&lt;br /&gt;
 		(c1, c2) = greatest.splitClusterIntoTwo();&lt;br /&gt;
 		initial_clusters.remove(greatest);&lt;br /&gt;
 		initial_clusters.push_back(c1);&lt;br /&gt;
 		initial_clusters.push_back(c2);&lt;br /&gt;
 	}&lt;br /&gt;
 }&lt;br /&gt;
 // фаза 3 - выполним слияние кластеров&lt;br /&gt;
 Cluster current_clusters[] = initial_clusters;&lt;br /&gt;
 bool already_merged[] = {false};&lt;br /&gt;
 Cluster clusters_merged[];&lt;br /&gt;
 // возвращает логическую переменную, показывающую,&lt;br /&gt;
 // произошло ли слияние или нет&lt;br /&gt;
 bool merge(int i, int j) {&lt;br /&gt;
 	if (already_merged(i) || already_merged(j)) {&lt;br /&gt;
 		return false;&lt;br /&gt;
 	}&lt;br /&gt;
 &lt;br /&gt;
 	Cluster c1 = current_clusters[i];&lt;br /&gt;
 	Cluster c2 = current_clusters[j];&lt;br /&gt;
 	&lt;br /&gt;
 	double RI = calcRI(c1, c2);&lt;br /&gt;
 	double RC = calcRC(c1, c2);&lt;br /&gt;
 	double similarity = pow(RI, alpha) * RC;&lt;br /&gt;
 	if (similarity &amp;gt; threshold) {&lt;br /&gt;
 		already_merged(i) == true;&lt;br /&gt;
 		already_merged(j) == true;&lt;br /&gt;
 		&lt;br /&gt;
 		Cluster merged = connect_clusters(i, j);&lt;br /&gt;
 		clusters_merged.push_back(merged);&lt;br /&gt;
 		&lt;br /&gt;
 		return true;&lt;br /&gt;
 	}&lt;br /&gt;
 	return false;&lt;br /&gt;
 }&lt;br /&gt;
 // слияние&lt;br /&gt;
 while (1) {&lt;br /&gt;
 	bool some_merging_happened = false;&lt;br /&gt;
 	for (each pair (i, j) in current_clusters) {&lt;br /&gt;
 		some_merging_happened ||= merge(i, j);&lt;br /&gt;
 	}&lt;br /&gt;
 	if (some_merging_happened) {&lt;br /&gt;
 		current_clusters = clusters_merged;&lt;br /&gt;
 		clusters_merged = null;&lt;br /&gt;
 		&lt;br /&gt;
 		already_merged = {false};&lt;br /&gt;
 	} else {&lt;br /&gt;
 		break;&lt;br /&gt;
 	}&lt;br /&gt;
 }&lt;br /&gt;
 // результат&lt;br /&gt;
 print current_clusters&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;n&amp;lt;/math&amp;gt; – размер входной выборки данных (иначе говоря, число точек). Также через &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; обозначим число начальных кластеров, появившихся после этапа 2 алгоритма, и для простоты анализа будем считать, что размер каждого из кластеров равен &amp;lt;math&amp;gt;\frac{n}{m}&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Построение графа &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ближайших соседей. Для нахождения &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей одной фиксированной вершины в общем случае требуется &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;  шагов, следовательно, для всего этапа требуется &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; шагов.&lt;br /&gt;
* Построение начального набора кластеров. Пусть дан граф &amp;lt;math&amp;gt;G=(V,E)&amp;lt;/math&amp;gt;. Один шаг алгоритма – разбиение кластера максимального размера на 2 подкластера – может быть выполнен за &amp;lt;math&amp;gt;O(|V|+|E|)&amp;lt;/math&amp;gt; шагов. Так как мы исходной точкой для данного этапа является граф &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-ближайших соседей, &amp;lt;math&amp;gt;|E|=O(|V|)&amp;lt;/math&amp;gt;, следовательно, шаг может быть выполнен за &amp;lt;math&amp;gt;O(|V|)=O(n)&amp;lt;/math&amp;gt; шагов. Суммарная же сложность всего этапа будет равна &amp;lt;math&amp;gt;O(n log(\frac{n}{m}))=O(n log(n))&amp;lt;/math&amp;gt;, так как в итоге получаются &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; кластеров.&lt;br /&gt;
* Сложность третьего этапа зависит от сложности вычисления относительной взаимной связанности и относительного взаимного сходства. Эти две операции вычисляются с помощью нахождения минимального разреза соответствующего кластера, что означает, что их сложность пропорциональна числу элементов в каждом кластере. В частности, время, необходимое на разделение каждого из изначальных m кластеров, равно &amp;lt;math&amp;gt;O(\frac{n}{m})&amp;lt;/math&amp;gt;, а суммарно необходимо &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; времени. Далее, необходимо сделать &amp;lt;math&amp;gt;m - 1&amp;lt;/math&amp;gt; объединений &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; изначальных кластеров, отсюда, суммарная сложность вычислений похожести равна &amp;lt;math&amp;gt;O(nm)&amp;lt;/math&amp;gt;. Суммарное время, требуемое для нахождение наиболее похожей пары кластеров, равно &amp;lt;math&amp;gt;O(m^2 log(m))&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Таким образом, итоговая сложность алгоритма равна &amp;lt;math&amp;gt;O(n^2+nm+n log n + m^2 log(m))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
Покажем информационный граф основной части алгоритма. Он представляет собой трехмерный набор точек-итераций главного цикла. Плоскость &amp;lt;math&amp;gt;(i,j)&amp;lt;/math&amp;gt; являет собой последовательную проверку на слияние пары кластеров с номерами &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;. Ось &amp;lt;math&amp;gt;h&amp;lt;/math&amp;gt; являет собой номер текущего набора кластеров, иначе говоря – номер итерации главного цикла. Операции слияния обозначены кружком с буквой “m” внутри.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Scheme4.jpg]]&lt;br /&gt;
&lt;br /&gt;
Из графа алгоритма видно, что переходить к следующей итерации главного цикла можно лишь тогда, когда будет завершена предыдущая (дуги-зависимости идут от операций слияния строго вверх).&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Как видно из графа алгоритма, операции слияния, находящиеся на одной итерации-плоскости главного цикла, не зависят друг от друга, и, следовательно, могут быть выполнены параллельно. Исходя из этого, предлагается следующая схема выполнения параллельного выполнения: каждая операция слияния на одной итерации главного цикла вызывается асинхронно, а в конце одной итерации главного цикла происходит ожидание окончания работы всех операций и подготовка к следующей итерации.&lt;br /&gt;
&lt;br /&gt;
Стоит заметить, что создание числа параллельных потоков, равного текущему количеству кластеров, вряд ли можно считать реальной задачей. Поэтому будем считать, что каждый параллельный поток вычисляет ровно один столбец матрицы-плоскости информационного графа, что означает, что параллельная сложность выполнения одной итерации алгоритма равна &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;. Высота полученного графа (то есть, число позиций по вертикальной оси) будет равна &amp;lt;math&amp;gt;O(log(n))&amp;lt;/math&amp;gt;, так как на каждом шаге цикла число кластеров уменьшается в среднем в 2 раза.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
Входные данные: массив &amp;lt;math&amp;gt;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;q_1, q_2, ..., q_n&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q_i&amp;lt;/math&amp;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;
Детерминированность: Важной особенностью данного алгоритма является его недетерминированность. Несмотря на то, что первая часть первого этапа детерминирована, остальные две части выполняются итеративно и останавливаются по достижении заданной точности.&lt;br /&gt;
&lt;br /&gt;
Приближенно оценить вычислительную мощность алгоритма можно как отношение числа операций к объему входных данных:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\frac{n^2+nm+nlog(n)+m^2log(m)}{n+m} = n + \frac{nlog(n)}{n+m} + \frac{m^2log(m)}{n+m} &amp;lt; n + log(n) + mlog(m)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
что являет собой сумму линейной, логарифмической и произведения линейной и логарифмической функций.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Существующая реализация алгоритма CHAMELEON есть в составе пакета CLUTO от авторов алгоритма &amp;lt;ref&amp;gt; [http://glaros.dtc.umn.edu/gkhome/views/cluto Data Clustering Software CLUTO - Software for Clustering High-Dimensional Datasets]. &amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;/div&gt;</summary>
		<author><name>Algoman</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:Ruslanlazovskiy/CHAMELEON&amp;diff=17593</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</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:Ruslanlazovskiy/CHAMELEON&amp;diff=17593"/>
		<updated>2016-11-16T11:09:37Z</updated>

		<summary type="html">&lt;p&gt;Algoman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n^2 / 2&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] ( разделы 1.1 - 1.4 , 1.7 , 1.8 ),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87|&amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] ( разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2 )&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики ( простейший пример - евклидова метрика ). Не следует путать задачу кластеризации с задачей классификации - в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения. Первоначально алгоритм был описан в статье&amp;lt;ref&amp;gt;CHAMELEON: A Hierarchical Clustering Algorithm Using Dynamic Modeling. George Karypis, Eui-Hong Han, Vipin Kumar. IEEE Computer 32(8): 68-75, 1999&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик ( возможные метрики будут подробно описаны далее ). Число получаемых в итоге кластеров в явном виде не задаётся.&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt; ( возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой. К исходным данным также относится набор параметров. Это &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество ближайших соседей на первом этапе алгоритма, &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - отношение количества вершин в наибольшем подграфе по отношению к общему числу объектов на втором этапе алгоритма, а также параметры &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - пороговые значения, после которых прекращается агломеративная кластеризация на третьем этапе. Следует особо отметить, что число получаемых в итоге кластеров заранее не известно, хотя на него и можно повлиять изменением значений перечисленных параметров.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей, где &amp;lt;math&amp;gt;V&amp;lt;/math&amp;gt; - множество вершин графа ( т.е. объекты ), а &amp;lt;math&amp;gt;E&amp;lt;/math&amp;gt; - множество ребер графа ( т.е. построенные связи между ближайшими соседями ). Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. Параметр &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; явно не задаётся, выполнение этого этапа алгоритма прекращается по выполнении описанных далее условий. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии анализа показателей сходства. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&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;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(nm + nlog{n} + mlog{m})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число исходных объектов, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - число малых кластеров, полученных после первого этапа работы. В случае &amp;quot;предельного&amp;quot; разбиения &amp;lt;math&amp;gt;m = n&amp;lt;/math&amp;gt; эта оценка превращается в &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;. В любом случае эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов (авторы оригинальной статьи в своих исследованиях подразумевают, что матрица смежности уже построена), что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Тогда оценка будет составлять &amp;lt;math&amp;gt;O(n^2 + nm + nlog{n} + mlog{m})&amp;lt;/math&amp;gt; операций или &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; в случае &amp;quot;предельного&amp;quot; разбиения.&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений ( для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON ( см. раздел &amp;quot;Существующие реализации&amp;quot; ). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;q - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами, где q - количество кластеров на этой итерации.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа в этих терминах - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации ( такая кластеризация, очевидно, не будет иметь практического смысла ), в то время как 2-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
===Локальность данных и вычислений===&lt;br /&gt;
===Возможные способы и особенности параллельной реализации алгоритма===&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Как можно увидеть из раздела &amp;quot;существующие реализации&amp;quot;, параллельной реализации алгоритма CHAMELEON на система с распределенной памятью найдено не было. Однако в &amp;lt;ref&amp;gt;Parallel Algorithm for the Chameleon Clustering Algorithm using Dynamic Modeling.  Rajnish Dashora, Harsh Bajaj, Akshat Dube, Geetha Mary .A. VIT University,Vellore. International Journal of Computer Applications (0975 – 8887) Volume 79 – No8, October 2013 &amp;lt;/ref&amp;gt;. приводится экспериментальный вариант параллельной реализации посредством OpenMP для систем с общей памятью.&lt;br /&gt;
&lt;br /&gt;
Основное внимание будет уделено исследованию масштабируемости алгоритма по размеру задачи, в пределах одного узла ( некоторый параллелизм достигается за счёт использования OpenMP ). Далее приводятся графики производительности в Гфлопс для различных размеров задачи. Эффективность работы алгоритма убывает на всей рассматриваемой области. Темпы убывания эффективности снижаются с ростом размера задачи.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON performance.png|800px]]&lt;br /&gt;
&lt;br /&gt;
===Динамические характеристики и эффективность реализации алгоритма===&lt;br /&gt;
===Выводы для классов архитектур===&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
С копией референсной реализации иерархической кластеризации, взятой с данного ресурса [http://us.codeforge.com/article/192925 Sequental], в случае неработоспособности последнего, можно ознакомиться здесь [http://pastebin.com/PhC4X0Cy Copy]&amp;lt;br/&amp;gt;&lt;br /&gt;
Последовательная реализация алгоритма CHAMELEON использовалась в статье &amp;lt;ref&amp;gt;Clustering Of Web Usage Data Using&lt;br /&gt;
Chameleon Algorithm, T.Vijaya Kumar, Dr. H.S.Guruprasad, International Journal of Innovative Research in Computer&lt;br /&gt;
and Communication Engineering, Vol. 2, Issue 6, June 2014&amp;lt;/ref&amp;gt;&lt;br /&gt;
Возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, например [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview METIS ], [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview hMETIS] и [https://cran.r-project.org/web/packages/RANN/index.html RANN].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf параллельная реализация].&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Краткий обзор алгоритма [http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Первоначальная статья от авторов алгоритма [http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Исследования возможной параллелизации алгоритма[http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|]&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Algoman</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%95%D0%BA%D0%B0%D1%82%D0%B5%D1%80%D0%B8%D0%BD%D0%B0%D0%9A%D0%BE%D0%B7%D1%8B%D1%80%D0%B5%D0%B2%D0%B0&amp;diff=17592</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%95%D0%BA%D0%B0%D1%82%D0%B5%D1%80%D0%B8%D0%BD%D0%B0%D0%9A%D0%BE%D0%B7%D1%8B%D1%80%D0%B5%D0%B2%D0%B0&amp;diff=17592"/>
		<updated>2016-11-16T11:07:02Z</updated>

		<summary type="html">&lt;p&gt;Algoman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Замечания к [[Участник:ЕкатеринаКозырева/Алгоритм_динамической_иерархической_кластеризации_CHAMELEON]] ==&lt;br /&gt;
&lt;br /&gt;
1) отсутствует оценка высоты и ширины ЯПФ параллельного алгоритма во врезке в начале статьи&lt;br /&gt;
&lt;br /&gt;
2) требуется какая-то подпись или ссылка на рисунок в п 1.1&lt;br /&gt;
&lt;br /&gt;
3) подпись к рисунку 1.2 должны быть выполнена средствами разметки, а не на самой картинке&lt;br /&gt;
&lt;br /&gt;
4) для оформления (псевдо) кода следует использовать тег &amp;lt;nowiki&amp;gt;&amp;lt;source lang=&amp;quot;...&amp;quot;&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
5) отсутствует оценка вычислительной мощности алгоритма в п 1.10 &lt;br /&gt;
&lt;br /&gt;
6) пункты 2.1 и 2.2 должны быть 2.4 и 2.7, согласно формату описания [[Структура_описания_свойств_алгоритмов]]&lt;br /&gt;
&lt;br /&gt;
7) список литературы оформлен неправильно - см. как сделано в [[Разложение_Холецкого_(метод_квадратного_корня)]]&lt;br /&gt;
&lt;br /&gt;
== Замечания к пункту 2.4 от 16.11.2016 == &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* отсутствует пункт 2.4&lt;/div&gt;</summary>
		<author><name>Algoman</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%90%D1%80%D1%82%D0%B5%D0%BC_%D0%A2%D0%B0%D1%80%D0%B0%D0%BD&amp;diff=17590</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%90%D1%80%D1%82%D0%B5%D0%BC_%D0%A2%D0%B0%D1%80%D0%B0%D0%BD&amp;diff=17590"/>
		<updated>2016-11-16T11:06:42Z</updated>

		<summary type="html">&lt;p&gt;Algoman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Замечания к [[Участник:Артем_Таран/Графо-ориентированный_алгоритм_кластеризации_CHAMELEON]] ==&lt;br /&gt;
&lt;br /&gt;
* отсутствует оценка вычислительной мощности алгоритма в п 1.10&lt;br /&gt;
&lt;br /&gt;
* В п.1.1. следует добавить информацию о том, известно ли число кластеров заранее [[Участник:Kronberg|Kronberg]] ([[Обсуждение участника:Kronberg|обсуждение]]) 16:26, 14 ноября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
* В п.1.2. наверное стоит отнести параметр k к исходным данным [[Участник:Kronberg|Kronberg]] ([[Обсуждение участника:Kronberg|обсуждение]]) 16:26, 14 ноября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
== Замечания к пункту 2.4 от 16.11.2016 == &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* отсутствует пункт 2.4&lt;/div&gt;</summary>
		<author><name>Algoman</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:Steve/%D0%93%D1%80%D0%B0%D1%84%D0%BE-%D0%BE%D1%80%D0%B8%D0%B5%D0%BD%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_CHAMELEON&amp;diff=17584</id>
		<title>Обсуждение участника:Steve/Графо-ориентированный алгоритм кластеризации CHAMELEON</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:Steve/%D0%93%D1%80%D0%B0%D1%84%D0%BE-%D0%BE%D1%80%D0%B8%D0%B5%D0%BD%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_CHAMELEON&amp;diff=17584"/>
		<updated>2016-11-16T10:57:56Z</updated>

		<summary type="html">&lt;p&gt;Algoman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Замечания к [[Участник:Steve/Графо-ориентированный_алгоритм_кластеризации_CHAMELEON]] ==&lt;br /&gt;
&lt;br /&gt;
0) требуется указать вклад(пункты) каждого автора&lt;br /&gt;
&lt;br /&gt;
1) отсутствует оценка вычислительной мощности алгоритма в п 1.10&lt;br /&gt;
&lt;br /&gt;
2) пункты 2.1 и 2.2 должны быть 2.4 и 2.7, согласно формату описания [[Структура_описания_свойств_алгоритмов]]&lt;br /&gt;
&lt;br /&gt;
3) список литературы оформлен неправильно - см. как сделано в [[Разложение_Холецкого_(метод_квадратного_корня)]]&lt;br /&gt;
&lt;br /&gt;
== Замечания к пункту 2.4 от 16.11.2016 == &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* отсутствует пункт 2.4&lt;/div&gt;</summary>
		<author><name>Algoman</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:Ruslanlazovskiy/CHAMELEON&amp;diff=17581</id>
		<title>Участник:Ruslanlazovskiy/CHAMELEON</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:Ruslanlazovskiy/CHAMELEON&amp;diff=17581"/>
		<updated>2016-11-16T10:54:29Z</updated>

		<summary type="html">&lt;p&gt;Algoman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Algoman}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n*m + n*log{n} + m*log{m})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt; - этап 1. &amp;lt;math&amp;gt;O(q)&amp;lt;/math&amp;gt; - отдельная итерация этапа 3.&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n^2 / 2&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Авторы статьи: &lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Ruslanlazovskiy|&amp;lt;b&amp;gt;Лазовский Р. А.&amp;lt;/b&amp;gt;] ( разделы 1.1 - 1.4 , 1.7 , 1.8 ),&lt;br /&gt;
[https://algowiki-project.org/ru/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D1%83%D1%81%D1%82%D0%B0%D1%84%D0%B0%D0%B5%D0%B2_%D0%AD%D0%BB%D1%8C%D0%B2%D0%B8%D0%BD_%D0%AD%D0%BB%D1%8C%D0%BC%D0%B0%D0%BD%D0%BE%D0%B2%D0%B8%D1%87|&amp;lt;b&amp;gt;Мустафаев Э. Э.&amp;lt;/b&amp;gt;] ( разделы 1.5 , 1.6 , 1.9 , 1.10 , 2.2 )&lt;br /&gt;
&lt;br /&gt;
==Свойства и структура алгоритма==&lt;br /&gt;
===Общее описание алгоритма===&lt;br /&gt;
CHAMELEON – алгоритм динамической иерархической кластеризации графа, то есть процесса разбиения графа на несколько подграфов-кластеров таким образом, что данные внутри одного кластера имеют максимально схожи, а данные в разных кластерах — максимально различны. В классических алгоритмах кластеризации схожесть объектов определяется с помощью некоторой метрики ( простейший пример - евклидова метрика ). Не следует путать задачу кластеризации с задачей классификации - в последней характеристики объекта, необходимые для попадания в тот или иной класс, известны заранее, в рассматриваемой же задаче они становятся известны в процессе решения. Первоначально алгоритм был описан в статье&amp;lt;ref&amp;gt;CHAMELEON: A Hierarchical Clustering Algorithm Using Dynamic Modeling. George Karypis, Eui-Hong Han, Vipin Kumar. IEEE Computer 32(8): 68-75, 1999&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON работает в 3 этапа. На первом этапе исходное множество объектов организуется в граф по принципу k ближайших соседей. На втором этапе этого граф разбивается на достаточно малые подграфы-кластеры. На третьем этапе происходит агломеративная иерархическая кластеризация полученных подграфов в соответствии с одной из выбранных метрик ( возможные метрики будут подробно описаны далее ). Число получаемых в итоге кластеров в явном виде не задаётся.&lt;br /&gt;
&lt;br /&gt;
===Математическое описание алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Исходные данные:&amp;lt;/b&amp;gt; Первоначально исходными данными алгоритма являются &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, каждый из которых соответствует одному объекту. На основании значений элементов этих векторов строится матрица смежности размера &amp;lt;math&amp;gt;n * n&amp;lt;/math&amp;gt; ( возможно сокращение требуемого объема памяти до &amp;lt;math&amp;gt;(n*(n - 1))/ 2&amp;lt;/math&amp;gt; в соответствии с выбранной метрикой. К исходным данным также относится набор параметров. Это &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество ближайших соседей на первом этапе алгоритма, &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - отношение количества вершин в наибольшем подграфе по отношению к общему числу объектов на втором этапе алгоритма, а также параметры &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - пороговые значения, после которых прекращается агломеративная кластеризация на третьем этапе. Следует особо отметить, что число получаемых в итоге кластеров заранее не известно, хотя на него и можно повлиять изменением значений перечисленных параметров.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Первый этап алгоритма:&amp;lt;/b&amp;gt; На первом этапе на основании матрицы смежности строится граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей, где &amp;lt;math&amp;gt;V&amp;lt;/math&amp;gt; - множество вершин графа ( т.е. объекты ), а &amp;lt;math&amp;gt;E&amp;lt;/math&amp;gt; - множество ребер графа ( т.е. построенные связи между ближайшими соседями ). Указанный граф не обязательно является связным.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Второй этап алгоритма:&amp;lt;/b&amp;gt; Граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; итеративно разбивается на множество подграфов &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \cup V_{i} = V, i = 1 .. m&amp;lt;/math&amp;gt;. Параметр &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; явно не задаётся, выполнение этого этапа алгоритма прекращается по выполнении описанных далее условий. На каждой итерации выбирается &amp;lt;math&amp;gt;G_{b}&amp;lt;/math&amp;gt; с числом вершин, наибольшим среди всех подграфов, имеющихся на данной итерации. Этот граф разбивается на 2 подграфа &amp;lt;math&amp;gt;G_{bi}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;G_{bj}&amp;lt;/math&amp;gt; таких, что 1) &amp;lt;math&amp;gt;min(V_{bi},V_{bj}) &amp;gt;= 0.25 * V_{b}&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ) и 2) &amp;lt;math&amp;gt;\sum{E_{kl}}, E_{kl} = (v_{k}, v_{l}), v_{k} \in V_{bi} , v_{l} \in V_{bj} &amp;lt;/math&amp;gt; минимальна среди всех разбиений, удовлетворяющих 1). Итеративный процесс прекращается, когда &amp;lt;math&amp;gt;\sum{v_{b}} &amp;lt;= q * \sum{v} , v_{b} \in V_{b} , e \in E&amp;lt;/math&amp;gt; ( имеется ввиду количество вершин ). Здесь &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - задаваемый параметр, на практике он варьируется от &amp;lt;math&amp;gt;0.01&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.05&amp;lt;/math&amp;gt;. Полученные подграфы называются малыми кластерами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Третий этап алгоритма:&amp;lt;/b&amp;gt; Множество кластеров &amp;lt;math&amp;gt;G_{i} = (V_{i}, E_{i}), i = 1 .. m&amp;lt;/math&amp;gt; итеративно преобразуется в множество кластеров &amp;lt;math&amp;gt;G_{j} = (V_{j}, E_{j}), j = 1 .. l&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;l &amp;lt;= m&amp;lt;/math&amp;gt;. Для этого вводятся следующие понятия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Это суть среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На основании этих показателей осуществляется агломеративная иерерхическая кластеризация. Существует две стратегии анализа показателей сходства. В первом случае для каждой пары кластеров &amp;lt;math&amp;gt;C{i}, C{j}&amp;lt;/math&amp;gt; проверяется истинность выражений &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;gt;= T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} &amp;gt;= T_{RC}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;T_{RI}, T_{RI}&amp;lt;/math&amp;gt; - заранее заданные пороговые значения. Если для некоторого &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; таких &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; несколько, то конкретная пара определяется по максимуму значения &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Во втором случае выбираются пары кластеров, максимизирующие функцию вида &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;. Здесь &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; - заданный пользователем параметр. В обоих случаях процесс останавливается либо когда на очередной итерации не находится подходящих пар кластеров, либо когда остаётся только один кластер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычисляемые данные:&amp;lt;/b&amp;gt; В процессе агломеративной кластеризации для всех объектов, т.е. всех вершин всех кластеров указывается индекс &amp;lt;math&amp;gt;j&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;
В алгоритме 3 основных вычислительных ядра, по одному на каждый этап алгоритма.&lt;br /&gt;
&lt;br /&gt;
На первом этапе алгоритма основная вычислительная нагрузка приходится на анализ матрицы смежности, необходимого для построения первоначального графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, так как для каждого объекта необходимо перебрать всех его соседей и выделить &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших по заданной метрике.&lt;br /&gt;
&lt;br /&gt;
На втором этапе наибольшее время занимает поиск подходящего разбиения очередного подграфа. В элементарном варианте этой процедуры необходимо перебрать все комбинации вершин в этом подграфе, удовлетворяющие условию 1) из математического описания алгоритма, и для каждой из них подсчитать значение, используемое в 2). &lt;br /&gt;
&lt;br /&gt;
На третьем этапе алгоритма вычислительное ядро полностью совпадает с самим этапом, то есть итерационным процессов агломеративной иерархической кластеризации, включающем в себя подсчёт выбранной метрики для каждой пары кластеров, имеющихся на очередной итерации.&lt;br /&gt;
&lt;br /&gt;
===Макроструктура алгоритма===&lt;br /&gt;
Как уже понятно из предыдущих разделов описания, алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап, строго говоря, соответствует отдельному алгоритму. В рамках этого описания макрооперациями будут считаться процедуры разбиения наибольшего подграфа на каждой итерации второго этапа алгоритма, а также процедура вычисления метрики для принятия решения об объединении кластеров на каждой итерации третьего этапа.&lt;br /&gt;
&lt;br /&gt;
===Схема реализации последовательного алгоритма===&lt;br /&gt;
&lt;br /&gt;
Схема представлена в виде C++-подобного псевдокода, макрооперации в алгоритме выделены в соответствии с предыдущим разделом описания.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // First stage.&lt;br /&gt;
 int k // Number of neighbors.&lt;br /&gt;
 float v[n][p] // Initial vectors.&lt;br /&gt;
 float M[n][n] // Adjacency matrix.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = 0; l &amp;lt; n; ++l) {&lt;br /&gt;
   M[i][l] = Compute_metric(v[i],v[l]);&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
 Graph max_graph // Structure/class that represents a graph.&lt;br /&gt;
 Neighbor_list list // Here neighbors are initially stored.&lt;br /&gt;
 max_graph.add_vertices // Vertices ~ initial vectors.&lt;br /&gt;
 for (int i = 0; i &amp;lt; n; ++i) {&lt;br /&gt;
  for (int l = i + 1; i &amp;lt; n; ++i) { // &amp;quot;Smart&amp;quot; version - we do not repeat same vertex combinations.&lt;br /&gt;
   if (neighbor_number &amp;lt; k) {&lt;br /&gt;
     add_neighbor(v[i],v[l]) // Just add.&lt;br /&gt;
   }else{&lt;br /&gt;
     substitute_neighbor(v[i],v[l]) // Check whether a new element is closer than some of the oldies.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
  max_graph.add_neighbors // Looks at neighbor lists of current vector and adds them&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Second stage. &lt;br /&gt;
 float percent // Determines when to stop splitting graphs. &lt;br /&gt;
 Graph graphs[n] // GRAPHS WILL MOST LIKELY TAKE LESS SPACE, IT&#039;S JUST THE UPPER LIMIT. &lt;br /&gt;
 max_graph = find_max_graph() // Biggest graph by number of vertices available. &lt;br /&gt;
 while (graph_size(max_graph) &amp;gt; n * percent) {&lt;br /&gt;
   Split_graph(max_graph); // Split the graph - a macro operation that represents the second phase.&lt;br /&gt;
 } &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;C++&amp;quot;&amp;gt;&lt;br /&gt;
 // Third stage. &lt;br /&gt;
 Graph graphs[m] // That&#039;s how many graphs we got. m &amp;lt;= n. &lt;br /&gt;
 bool pairs_exist // Check if the&#039;re pairs of clusters to unite.&lt;br /&gt;
 while (num_graphs &amp;gt; 1 &amp;amp;&amp;amp; pairs_exist){&lt;br /&gt;
  pairs_exist = false // So we don&#039;t repeat if it fails.&lt;br /&gt;
  for (int i = 0; i &amp;lt; m; ++i) {&lt;br /&gt;
   for (int l = i + 1; l &amp;lt; m; ++l) { // Also a &amp;quot;Smart&amp;quot; version.&lt;br /&gt;
     check_pair(pairs_exist, graphs[i], graphs[l]); // Check whether graphs are similar enough by some metrics.&lt;br /&gt;
     if (pairs_exist) { Unite_graphs(graphs[i], graphs[l]) }; // Pairs_exist is set to true if something&#039;s found.&lt;br /&gt;
   }&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Последовательная сложность алгоритма===&lt;br /&gt;
&lt;br /&gt;
Общая временная сложность последовательного варианта алгоритма CHAMELEON определяется как &amp;lt;math&amp;gt;O(nm + nlog{n} + mlog{m})&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число исходных объектов, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - число малых кластеров, полученных после первого этапа работы. В случае &amp;quot;предельного&amp;quot; разбиения &amp;lt;math&amp;gt;m = n&amp;lt;/math&amp;gt; эта оценка превращается в &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;. В любом случае эта оценка не учитывает необходимости построения матрицы смежности по исходному набору векторов (авторы оригинальной статьи в своих исследованиях подразумевают, что матрица смежности уже построена), что означает дополнительные &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций. Тогда оценка будет составлять &amp;lt;math&amp;gt;O(n^2 + nm + nlog{n} + mlog{m})&amp;lt;/math&amp;gt; операций или &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; в случае &amp;quot;предельного&amp;quot; разбиения.&lt;br /&gt;
Следует также обратить внимание, что это оценка по числу не сложений и умножений, а достаточно крупных операций. Например, вычисление метрики между двумя векторами рассматривается как одна операция, а она включает в себя &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;2n&amp;lt;/math&amp;gt; сложений ( для вычисления квадратичной нормы разности векторов).&lt;br /&gt;
&lt;br /&gt;
===Информационный граф===&lt;br /&gt;
&lt;br /&gt;
Информационный граф дан в соответствии с макроструктурой алгоритма. Следует отметить, что имеются успешные попытки распараллелить 2 и 3 этапы алгоритма CHAMELEON ( см. раздел &amp;quot;Существующие реализации&amp;quot; ). Однако они включают в себя модификацию исходного алгоритма. Также возможно распараллеливание выборки пар кластеров и подсчёта их метрик внутри каждой из вершин stage_3_iter. Структура информационного графа внутри этих итераций аналогична структуре информационного графа первого этапа алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON ruslanlazovskiy.png]]&lt;br /&gt;
&lt;br /&gt;
===Ресурс параллелизма алгоритма===&lt;br /&gt;
&lt;br /&gt;
Параллельную сложность алгоритма CHAMELEON следует оценивать отдельно для каждого этапа.&lt;br /&gt;
На первом этапе алгоритм поиска &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей может быть выполнен за &amp;lt;math&amp;gt;n - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя векторами.&lt;br /&gt;
На втором этапе итерации алгоритма выполняются строго последовательно, а распараллеливание алгоритма внутри итерации не относится к теме статьи.&lt;br /&gt;
На третьем этапе итерации также выполняются последовательно, однако возможно распараллеливание обработки пар кластеров внутри итерации. Каждая итерация может быть выполнена за &amp;lt;math&amp;gt;q - 1&amp;lt;/math&amp;gt; вычислений значения метрики между двумя кластерами, где q - количество кластеров на этой итерации.&lt;br /&gt;
&lt;br /&gt;
===Входные и выходные данные алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Входные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; - набор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; векторов длины &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;. &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - число, определяющиее количество ближайших соседей, по которым строится первоначальный граф. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Выходные данные:&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - вектор длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, значение &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го элемента указывает на принадлежность соответствующего вектора одному из кластеров.&lt;br /&gt;
&lt;br /&gt;
===Свойства алгоритма===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Соотношение последовательной и параллельной сложности:&amp;lt;/b&amp;gt; Различные этапы алгоритма строго последовательны относительно друг друга. На первом этапе отношение последовательной сложности алгоритма к параллельной есть &amp;lt;math&amp;gt;n/2&amp;lt;/math&amp;gt;. На втором и третьем этапах различные итерации последовательны относительно друг друга. Однако внутри итераций допускается некоторый параллелизм. Например, для итераций третьего этапа в наилучшем случае отношение сложности последовательной реализации к параллельной есть &amp;lt;math&amp;gt;q/2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; - число кластеров на конкретной итерации.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Вычислительная мощность:&amp;lt;/b&amp;gt; графовые алгоритмы, вообще говоря, обладают низкой вычислительной мощностью. В случае CHAMELEON вычислительная мощность первого этапа равна &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;. Для второго и третьего этапов оценка вычислительной мощности по сложениям и умножениям затруднительна, однако в терминах макроопераций можно дать грубую оценку. Вычислительная мощность каждой итерации второго этапа - &amp;lt;math&amp;gt;1 / \sum C_n^k&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число вершин в выбранном подграфе, а &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; варьируется от &amp;lt;math&amp;gt;0.25 * n&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;0.5 * n&amp;lt;/math&amp;gt;. Вычислительная мощность каждой итерации третьего этапа в этих терминах - &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью описываемого алгоритма является его недетерминированность. Условия завершения как 2-го, так и 3-го этапа позволяют обозначить CHAMELEON как итерационный алгоритм с выходом по точности. При этом детерминированность 2-го этапа алгоритма можно обеспечить указанием вырожденных условий кластеризации ( такая кластеризация, очевидно, не будет иметь практического смысла ), в то время как 2-ый этап является недетерминированным всегда.&lt;br /&gt;
&lt;br /&gt;
==Программная реализация алгоритма==&lt;br /&gt;
===Особенности реализации последовательного алгоритма===&lt;br /&gt;
===Локальность данных и вычислений===&lt;br /&gt;
===Возможные способы и особенности параллельной реализации алгоритма===&lt;br /&gt;
===Масштабируемость алгоритма и его реализации===&lt;br /&gt;
&lt;br /&gt;
Как можно увидеть из раздела &amp;quot;существующие реализации&amp;quot;, параллельной реализации алгоритма CHAMELEON на система с распределенной памятью найдено не было. Однако в &amp;lt;ref&amp;gt;Parallel Algorithm for the Chameleon Clustering Algorithm using Dynamic Modeling.  Rajnish Dashora, Harsh Bajaj, Akshat Dube, Geetha Mary .A. VIT University,Vellore. International Journal of Computer Applications (0975 – 8887) Volume 79 – No8, October 2013 &amp;lt;/ref&amp;gt;. приводится экспериментальный вариант параллельной реализации посредством OpenMP для систем с общей памятью.&lt;br /&gt;
&lt;br /&gt;
Основное внимание будет уделено исследованию масштабируемости алгоритма по размеру задачи, в пределах одного узла ( некоторый параллелизм достигается за счёт использования OpenMP ). Далее приводятся графики производительности в Гфлопс для различных размеров задачи. Эффективность работы алгоритма убывает на всей рассматриваемой области. Темпы убывания эффективности снижаются с ростом размера задачи.&lt;br /&gt;
&lt;br /&gt;
[[File:CHAMELEON performance.png|800px]]&lt;br /&gt;
&lt;br /&gt;
===Динамические характеристики и эффективность реализации алгоритма===&lt;br /&gt;
===Выводы для классов архитектур===&lt;br /&gt;
===Существующие реализации алгоритма===&lt;br /&gt;
С копией референсной реализации иерархической кластеризации, взятой с данного ресурса [http://us.codeforge.com/article/192925 Sequental], в случае неработоспособности последнего, можно ознакомиться здесь [http://pastebin.com/PhC4X0Cy Copy]&amp;lt;br/&amp;gt;&lt;br /&gt;
Последовательная реализация алгоритма CHAMELEON использовалась в статье &amp;lt;ref&amp;gt;Clustering Of Web Usage Data Using&lt;br /&gt;
Chameleon Algorithm, T.Vijaya Kumar, Dr. H.S.Guruprasad, International Journal of Innovative Research in Computer&lt;br /&gt;
and Communication Engineering, Vol. 2, Issue 6, June 2014&amp;lt;/ref&amp;gt;&lt;br /&gt;
Возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, например [http://glaros.dtc.umn.edu/gkhome/metis/metis/overview METIS ], [http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview hMETIS] и [https://cran.r-project.org/web/packages/RANN/index.html RANN].&amp;lt;br/&amp;gt;&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON в графовых библиотеках мною найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь [http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf параллельная реализация].&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Краткий обзор алгоритма [http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Первоначальная статья от авторов алгоритма [http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf|]&amp;lt;br/&amp;gt;&lt;br /&gt;
Исследования возможной параллелизации алгоритма[http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf|]&amp;lt;br/&amp;gt;&lt;/div&gt;</summary>
		<author><name>Algoman</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:Ruslanlazovskiy&amp;diff=17580</id>
		<title>Обсуждение участника:Ruslanlazovskiy</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:Ruslanlazovskiy&amp;diff=17580"/>
		<updated>2016-11-16T10:54:03Z</updated>

		<summary type="html">&lt;p&gt;Algoman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Замечания к [[Участник:Ruslanlazovskiy/CHAMELEON]] ==&lt;br /&gt;
&lt;br /&gt;
1) все ссылки в статье не работают&lt;br /&gt;
&lt;br /&gt;
2) список литературы оформлен неправильно - см. как сделано в [[Разложение_Холецкого_(метод_квадратного_корня)]]&lt;br /&gt;
&lt;br /&gt;
3) для оформления (псевдо) кода следует использовать тег &amp;lt;nowiki&amp;gt;&amp;lt;source lang=&amp;quot;...&amp;quot;&amp;gt;&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Мои правки ==&lt;br /&gt;
&lt;br /&gt;
2) и 3) теперь сделаны как надо. В 1) не удалось поправить самую первую ссылку, ресурс с последовательной реализацией действительно умер.&lt;br /&gt;
&lt;br /&gt;
== Замечания к статье про Хамелеон (ещё порция) ==&lt;br /&gt;
&lt;br /&gt;
* Ссылки на авторов и список литературы - присоединяюсь к замечаниям. Список литературы действительно всего из одного наименования? [[Участник:Kronberg|Kronberg]] ([[Обсуждение участника:Kronberg|обсуждение]]) 14:09, 14 ноября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
* В разделе 1 пояснить, нужно ли заранее знать число кластеров. Это неясно и из описания входных и выходных данных, должно же оно быть хоть где-нибудь [[Участник:Kronberg|Kronberg]] ([[Обсуждение участника:Kronberg|обсуждение]]) 14:09, 14 ноября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
* Раздел 1.2. Когда вводим граф, желательно пояснить аргументы V и E в скобках. Аналогично с параметром m, который встречается впервые [[Участник:Kronberg|Kronberg]] ([[Обсуждение участника:Kronberg|обсуждение]]) 14:09, 14 ноября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
* Раздел 1.6. Стоит сделать логарифм красивей [[Участник:Kronberg|Kronberg]] ([[Обсуждение участника:Kronberg|обсуждение]]) 14:09, 14 ноября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
== Правки - порция 2. ==&lt;br /&gt;
&lt;br /&gt;
* В список литературы добавлена статья с исследованием параллелизма. Остальные найденные статьи по Chameleon представляют собой кальку с оригинальной статьи ( первый пункт в списке ) в разделе описания алгоритма + описание задачи, для которой применялся алгоритм, для примера добавил одну из таких статей.&lt;br /&gt;
* Сделано&lt;br /&gt;
* Сделано&lt;br /&gt;
* Поправил, добавил описание &amp;quot;предельного&amp;quot; случая.&lt;br /&gt;
&lt;br /&gt;
== Замечания к пункту 2.4 == &lt;br /&gt;
&lt;br /&gt;
* Отсутствуют подписи к меткам на оси числа процессов&lt;br /&gt;
* Желательно сделать крупнее размер шрифта подписей&lt;/div&gt;</summary>
		<author><name>Algoman</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:Bagnikita/Face_Recognition&amp;diff=15737</id>
		<title>Участник:Bagnikita/Face Recognition</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:Bagnikita/Face_Recognition&amp;diff=15737"/>
		<updated>2016-11-02T09:59:41Z</updated>

		<summary type="html">&lt;p&gt;Algoman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Algoman}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Распознавание лиц&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(E(w,h,c)+n*d+n*logn+n*logk+CNNConst)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(k)&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;w*h*c&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;O(k)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Основные авторы описания: [[Участник:Bagnikita|Н.Ю.Багров]]&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Распознавание лиц при помощи компьютера было впервые предложено в 1966 г. Woody Bledsoe и др. В первой системе использовался графический планшет, на котором было необходимо вручную отметить ключевые особенности на лице (брови, губы и тд). Система в дальнешейм использовала расстояния между этими точками для сравнения разных изображений. Поскольку требовалось много ручной работы, то оператор мог обработать около 40 изображений в час. В 1997 была создана система, которая непосредственно работала с видеоданными и могла применяться на практике. В дальшейшем с увеличением производительности вычислительных систем появились более качественные алгоритмы, но они заметно уступали человеку на данной задаче. С появлением высокороизводительных видеокарт в 2014 году появились системы&amp;lt;ref&amp;gt;Taigman Y. et al. Deepface: Closing the gap to human-level performance in face verification //Proceedings of the IEEE Conference on Computer Vision and Pattern Recognition. – 2014. – С. 1701-1708.&amp;lt;/ref&amp;gt;, точность которых уже превышала точность оператора (человека). Основное преимущество таких систем в том, что они могут обрабатывать большие объемы данных - производительность человека намного ниже (требуется несколько секунд на сравнение пары изображений). &lt;br /&gt;
&lt;br /&gt;
Задачу распознавания лиц можно разбить на несколько этапов:&lt;br /&gt;
&lt;br /&gt;
* обучение нейронной сети&lt;br /&gt;
* построение биометрического шаблона&lt;br /&gt;
* сравнение биометрических шаблонов&lt;br /&gt;
* поиск в базе и формирование результата&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Алгоритм состоит из построения биометрических шаблонов (дескрипторов) по изображению и поиску заданного шаблона в базе уже вычисленных дескрипторов. &lt;br /&gt;
&lt;br /&gt;
В дальшейшем будем рассматривать только сверточные нейронные сети. Классические архитектуры нейронных сетей с полносвязными слоями неприменимы на практике для анализа изображений, поскольку количество параметров такой сети экспоненциально возрастает с размером входных данных и количеством слоев. В таких сетях каждый нейрон не связан со всеми нейронами предыдущего слоя, а домножается на некоторый коэффициент (ядро свертки) по всему изображению. Таким образом, каждый такой слой применяет операцию свертки ко входам со своими коэффициентами, что заметно уменьшает число весов в нейронной сети. Это позволяет уменьшить потребление памяти и эффект переобучения сети, который проявляется в том, что сеть хорошо работает на классификации элементов обучающей выборки и хуже на валидационной.&lt;br /&gt;
&lt;br /&gt;
==== Обучение сверточной нейронной сети ====&lt;br /&gt;
&lt;br /&gt;
Для обучения нейронной сети используется стохастический градиентный спуск. Начальные веса сети устанавливаются случайными. Заметим, что существенное время занимают сверточные и полносвязные слои. Их можно свести к операции перемножения матриц следуюим образом:&lt;br /&gt;
* пусть размерность фильтра свертки k*k&lt;br /&gt;
* скопируем блоки исходного изображения размером k*k в столбцы новой матрицы&lt;br /&gt;
* умножим эту матрицу на коэффициеты фильтра свертки&lt;br /&gt;
* полученная матрица будет результатом применения свертки к входному изображению&lt;br /&gt;
&lt;br /&gt;
Сложность задачи вычисления свертки зависит квадратично от размера фильтра и линейно от количества выходных данных.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;FeatureMap = A^{n, w * h} * B^{w * h, c * k^2}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;FeatureMap&amp;lt;/math&amp;gt; - результат применения свертки, а &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - входное изображение и матрица весов слоя нейронной сети&lt;br /&gt;
&lt;br /&gt;
Существуют библиотеки, например, NVIDIA cuDNN&amp;lt;ref&amp;gt;https://developer.nvidia.com/cudnn&amp;lt;/ref&amp;gt;) которые решают данную задачу более эффективно. Например, свертки размером 3x3, 5x5 могут быть реализованы с использованием FFT (что работает на видеокарте быстрее, чем умножение матриц)&lt;br /&gt;
&lt;br /&gt;
==== Построение биометрического шаблона ====&lt;br /&gt;
&lt;br /&gt;
Будем называть биометрическим шаблоном вектор &amp;lt;math&amp;gt;{R}^d&amp;lt;/math&amp;gt;, который является представлением лица человека. Этот вектор получается после применения нейронной сети к изображению - в качестве такого вектора используют отклики с одного последних слоев нейронной сети. Для обеспечения возможности сравнивать между собой эти шаблоны вектор нормализуют.&lt;br /&gt;
&lt;br /&gt;
==== Сравнение биометрических шаблонов ====&lt;br /&gt;
&lt;br /&gt;
На предыдущем этапе был получен вектор значений &amp;lt;math&amp;gt;D={A}^d&amp;lt;/math&amp;gt;, где d - размерность дескриптора. Можно рассматривать достаточно много различных оценивающих функций (метриками их называть некорректно, т.к для них не всегда выполняется неравенство треугольника). Например, в качестве такой функции можно рассматривать cosine distance - косинус угла между векторами-признаками в d-мерном пространстве. Также достаточно часто используют L2 метрику, либо более сложные контрукции, такие как JointBayesian&amp;lt;ref&amp;gt;Chen D. et al. Bayesian face revisited: A joint formulation //European Conference on Computer Vision. – Springer Berlin Heidelberg, 2012. – С. 566-579.&amp;lt;/ref&amp;gt;. У всех таких &amp;quot;метрик&amp;quot; есть преимущества и недостатки, например в L2 можно легко проводить кластеризацию, тогда как в JointBayes и cosine metric нет. JointBayes можно дообучить на целевой выборке и повысить точность работы алгоритма.&lt;br /&gt;
&lt;br /&gt;
==== Поиск в базе и формирование результата ====&lt;br /&gt;
&lt;br /&gt;
Предположим, что для каждого человека в базе есть несколько фотографий. Тогда после выполнения операции сравнения биометрических шаблона изображения-запроса &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt; и всех изображений в базе &amp;lt;math&amp;gt;G={g1,g2,...,gn}&amp;lt;/math&amp;gt; необходимо выбрать результат с максимальным значением оценивающей функции для данного человека. Т.е необходимо оставить в результате только уникальные по людям совпадения, выбрав при этом максимальное значение при удалении дубликатов по людям.&lt;br /&gt;
&lt;br /&gt;
После выполнения поиска в базе необходимо произвести нормализацию полученных значений оценивающей функции. В системах распознавания лиц обычно используют диапазон [0.0 - 1.0], где 0.0 означает минимальное сходство двух изображений лиц, а 1.0 максимальное.&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;E(w,h,c)&amp;lt;/math&amp;gt; сложность операции вычисления биометричсекого шаблона по входному изображению лица человека. Поскольку сверточной нейронной сети с полносвязными слоями должно подаваться на вход изображения фиксированного размера, то необходимо изменить разрешение исходного изображения. В данной реализации алгоритма распознавания лиц используется билинейная интерполяция. Нейронная сеть получает на вход одноканальные изображения размером &amp;lt;math&amp;gt;100*100&amp;lt;/math&amp;gt;. Поэтому число необходимых операций (по операциям умножения) можно оценить как &amp;lt;math&amp;gt;O(w*h*c) + O(100 * 100 * 6) = O(w*h*c) + Const&amp;lt;/math&amp;gt;. На практике эта константа существенна, поскольку эти операции неоднородны по памяти.&lt;br /&gt;
&lt;br /&gt;
Непосредственно время работы нейронной сети существенно зависит от предложенной архитектуры (глубины сети, типов слоев и числа выходов каждого слоя).&lt;br /&gt;
&lt;br /&gt;
В реализации, предлолженной в практической части, используются более 10 сверточных слоев. Количестве операций можно оценить исходя из количества весов связей в нейронной сети - 80M и размера сверток &amp;lt;math&amp;gt;3*3&amp;lt;/math&amp;gt;. Оценка числа операций получилась ~2 GFlops на одну операцию применения нейросети (forward pass, 180ms). Она согласуется с реальным временем работы системы и производительностью системы на тесте linpack (130GFlops 4 cores) на ноутбуке.&lt;br /&gt;
&lt;br /&gt;
==== Поиск в базе ====&lt;br /&gt;
&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;M(x,y)=\frac{(x,y)}{\lVert x \lVert * \lVert y \lVert}&amp;lt;/math&amp;gt;. Заметим, что вектора &amp;lt;math&amp;gt;x, y&amp;lt;/math&amp;gt; уже нормированы на предыдущем этапе. Поэтому число операций для вычисления метрики составляет &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; умножений и &amp;lt;math&amp;gt;d - 1&amp;lt;/math&amp;gt; сложений, где d - размерность дескриптора. Если размер базы &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, то число операций &amp;lt;math&amp;gt;O(n*d+n*(d-1))=O(n*d)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===== Агрегация результатов по людям =====&lt;br /&gt;
&lt;br /&gt;
Для выполнения операции unique (без использования дополнительной памяти) необходимо отсортировать элементы (person_id, match_score) массива по ключу person_id, а при совпадении по score. После этого можно за линейное время удалить дубликаты по person_id, оставив первый элемент (который будет максимальным по match_score). Сложность таких операций &amp;lt;math&amp;gt;O(n*logn+n)=O(n*logn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===== Cортировка по убыванию метрики сходства двух изображений =====&lt;br /&gt;
&lt;br /&gt;
Финальная сортировка по match_score будет выполнена за O(n*logk), где k - количество результатов в выдаче. Обычно на практике число k не более 1000, поскольку обработка результата чаще всего производится вручную оператором (человеком).&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Алгоритм содержит вычисление биометричиского шаблона, который на этой странице не приводится. Используется готовая бибилотека распознавания лиц [http://tevian.ru Tevian FaceSDK]. Предложенная параллельная реализация может работать с любой системой распознавания лиц, для которой выполнены следующие условия:&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++):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&#039;python&#039;&amp;gt;&lt;br /&gt;
desc = enroll(Image) # Image - изображение лица человека&lt;br /&gt;
matches = {}&lt;br /&gt;
for gallery_entry in G:&lt;br /&gt;
    if matches.get(gallery_entry.person_id, None) is None:&lt;br /&gt;
        matches[gallery_entry.person_id] = 0.0&lt;br /&gt;
    matches[gallery_entry.person_id] = max(matches[gallery_entry.person_id], match(desc, gallery_entry.descriptor))&lt;br /&gt;
matches = sorted(key = lambda x: x[1], matches.items())&lt;br /&gt;
return [x[0], applyMapping(x[1]) for x in matches]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Если рассматривать всю последовательность действий (построение шаблона, поиск в базе), то сложность алгоритма &amp;lt;math&amp;gt;O(E(w,h,c)+n*d+n*logn+n*logk+CNNConst)&amp;lt;/math&amp;gt;, где&lt;br /&gt;
*&amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - число элементов в базе&lt;br /&gt;
*&amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt; - размерность биометрического шаблона&lt;br /&gt;
*&amp;lt;math&amp;gt;E(w,h,c)&amp;lt;/math&amp;gt; - сложность обработки изображения размером (width*height*channels) до необходимого размера для нейросети&lt;br /&gt;
*&amp;lt;math&amp;gt;n*d&amp;lt;/math&amp;gt; - число операций для вычисления метрики между запросом и базой&lt;br /&gt;
*&amp;lt;math&amp;gt;n*logn&amp;lt;/math&amp;gt; - сортировка результата для удаления дубликатов&lt;br /&gt;
*&amp;lt;math&amp;gt;n*logk&amp;lt;/math&amp;gt; - сортировка результата по значению оценивающей функции&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
&lt;br /&gt;
На первом шаге необходимо построить биометрический шаблон - поскольку внути алгоритма используется нейросеть, то эти вычисления обычно выполняются на видеокартах. В этом разделе подробно не рассматривается работа нейросети, поэтому можно считать, что ему соответствует одна вершина в графе.&lt;br /&gt;
&lt;br /&gt;
На втором шаге уже есть посчитанный биометрический шаблон (дескриптор) - его необходимо сопоставить в базой (пусть в ней N дескрипторов). Предположим, что доступно Q исполнителей (процессов или потоков). Тогда возможна паралельная обработка Q диапазонов базы размером N/Q. Для каждого такого вычисления длина последовательной части &amp;lt;math&amp;gt;N/Q*d&amp;lt;/math&amp;gt;, где d - размерность дескриптора.&lt;br /&gt;
&lt;br /&gt;
На третьем шаге производится агрегация полученных результатов сопоставнения длины k с один общий список, отсортированный по убыванию меры сходства изображений. Здесь аналогично можно рассматривать параллельную сортировку на Q вычислителях.&lt;br /&gt;
&lt;br /&gt;
Видно, что у алгоритма большой ресурс по возможности распараллеливания за счет возможности параллельной реализации практически любой его части.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Facerecognition-graph.png|thumb|center|700px|Рисунок 0. Граф параллельного алгоритма]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Сложность параллельного алгоритма, в предположении доступности q узлов: &amp;lt;math&amp;gt;O(k*logk+q*(log(k*q))^2+\frac{n}{q}*(d+log(\frac{n}{q}))+\lambda*(k*log(q)+q*(log(q*k))^2))&amp;lt;/math&amp;gt;, где&lt;br /&gt;
* n - размер базы изображений лиц&lt;br /&gt;
* d - размерность биометрического шаблона&lt;br /&gt;
* k - количество результатов в выдаче (k &amp;lt;&amp;lt; n)&lt;br /&gt;
* &amp;lt;math&amp;gt;\lambda&amp;lt;/math&amp;gt; - флаг (0 или 1), нужно ли производить агрегацию результатов по людям&lt;br /&gt;
&lt;br /&gt;
Данная оценка получена с применением [http://darwin.bth.rwth-aachen.de/opus3/volltexte/2010/3502/pdf/3502.pdf параллельной сортировки].&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Входные данные:&lt;br /&gt;
* изображение &amp;lt;math&amp;gt;P\in{R}^{w*h*c}&amp;lt;/math&amp;gt;, где w,h,c - ширина, высота, число каналов&lt;br /&gt;
* база изображений лиц &amp;lt;math&amp;gt;G={g_1,g_2,g_3,...,g_n}, g_i\in{T}&amp;lt;/math&amp;gt;&lt;br /&gt;
* T - объект, состоящий из биометрического шаблона и порядкового номера человека&lt;br /&gt;
&lt;br /&gt;
Выходные данные*&lt;br /&gt;
* список &amp;lt;math&amp;gt;L={l_1,l_2,...,l_k}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;l_i\in{T}&amp;lt;/math&amp;gt;&lt;br /&gt;
* T - объект, состоящий из числа (мера сходства двух изображений) и id (порядкового номера) человека в базе&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Основная проблема при реализации параллельной версии данного алгоритма - необходимость сортировки результатов. Исходя из размеров базы важно правильно выбрать количество вычислителей, поскольку в ряде случаев сортировка будет работать очень быстро (число элементов будет значительно меньше объема базы) и не потребуется реализация параллельной сортировки. &lt;br /&gt;
&lt;br /&gt;
Другая проблема - низкая вычислительная сложность самого алгоритма и большое число обращений к памяти. При реализации важно выделять память большими блоками для успешного чтения из кэша процессора.&lt;br /&gt;
&lt;br /&gt;
Из преимуществ данного алгоритма можно назвать низкую нагрузку на сеть при обмене данными, возможность работы на множестве систем (MPI, hadoop и тд), посколько объем данных, передаваемых между узлами небольшой. Для практической реализации не требуется использования специальных коммуникаций с низкой задержкой (обмены происходят достаточно редко, время доставки сообщений не критично).&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Построение биометрических шаблонов выполнено при помощи библиотеки распознавания лиц Tevian FaceSDK&amp;lt;ref&amp;gt;http://tevian.ru/product/facesdk&amp;lt;/ref&amp;gt;. В этом разделе приводится эффективность параллельной реализации сравнения изображени лица с некоторой базой лиц. &lt;br /&gt;
&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
В текущей версии алгоритма применяется векторизация с использованием FMA3 инструкций, что позволяет значительно ускорить работу программы. При выполнении оценки производительности системы использовалась простая реализация cosine метрики (цикл для вычисления скалярного произведения) и с использованием FMA инстукций.&lt;br /&gt;
&lt;br /&gt;
Псевдокод операции mm256_fmadd (intel)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;fortran&amp;quot;&amp;gt;&lt;br /&gt;
FOR j := 0 to 7&lt;br /&gt;
    i := j*32&lt;br /&gt;
    dst[i+31:i] := (a[i+31:i] * b[i+31:i]) + c[i+31:i]&lt;br /&gt;
ENDFOR&lt;br /&gt;
dst[MAX:256] := 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В результате тестирования (процессор 6300HQ, ноутбук, база 30М биометрических шаблонов) однопоточной программы было установлено, что FMA3 версия в 5 раз быстрее по сравнению с обычным циклом (880ms vs 4600ms). Все дальнейшие экспериенты будут проводиться с FMA3 реализацией (если не указано иначе). Компиляция производится gcc 5.4 с флагами &amp;lt;code&amp;gt;-O3 -static-libgcc -static-libstdc++ -mavx -mavx2 -mfma -fopenmp&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ниже приводится пример кода для вычисления дескриптора:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot;&amp;gt;&lt;br /&gt;
pp = descriptor;&lt;br /&gt;
pg = gallery_ptr;&lt;br /&gt;
__m256 sum = _mm256_setzero_ps();&lt;br /&gt;
for(int j = 0; j &amp;lt; 16; ++j, pp += 8, pg += 8) {&lt;br /&gt;
    sum = _mm256_fmadd_ps(_mm256_load_ps(pp), _mm256_load_ps(pg), sum);&lt;br /&gt;
}&lt;br /&gt;
const __m128 x128 = _mm_add_ps(_mm256_extractf128_ps(sum, 1), _mm256_castps256_ps128(sum));&lt;br /&gt;
const __m128 x64 = _mm_add_ps(x128, _mm_movehl_ps(x128, x128));&lt;br /&gt;
const __m128 x32 = _mm_add_ss(x64, _mm_shuffle_ps(x64, x64, 0x55));&lt;br /&gt;
score = _mm_cvtss_f32(x32);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для сортировки результатов и агрегации по людям используются функции из stl - вполне возможно, что можно реализовать более эффективно.&lt;br /&gt;
&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
&lt;br /&gt;
Данный алгоритм производит вычисления скалярных произведений, поэтому на этом этапе все обращения к памяти обладают свойством локальности. Биометрический шаблон полностью помещается в кэш память любого современного процессора, данные под базу изобрежний выделяются в виде больших непрерывных блоков памяти. &lt;br /&gt;
&lt;br /&gt;
Сортировка результатов также обладает свойством локальности, поскольку массив хранится непрерывно в памяти. При небольшом размере базы (1-10M изображений) он может полностью поместиться в кэш памяти.&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Алгоритм построен по модели map/reduce. В map происходит вычисление скалярных произведений дескриптора-запроса и элементов базы. В reduce происходит сортировка и удаление повторов.&lt;br /&gt;
&lt;br /&gt;
Исходная база разбирается на блоки (chunks) по 1M биометрических шаблонов, каждый такой блок обрабатывается независимо в своем потоке (или процессе). Важно то, что в результате работы алгоритма на каждом блоке в результате получается небольшой объем данных - &amp;lt;math&amp;gt;k*(sizeof(float)+sizeof(int32_t))&amp;lt;/math&amp;gt;. Такие данные можно легко передать по медленному каналу с высокой задержкой (не требуется использование InfiniBand). Также данный алгоритм можно запускать как на MPI кластерах с передачей сообщений, так и на hadoop кластерах.&lt;br /&gt;
&lt;br /&gt;
Для сортировки результатов можно применять параллельную сортировку (которая ассимптотически) лучше, но на практике это не нужно из-за разумного ограчения на число результатов. Часто их просматривает вручную оператор системы, поэтому больше нескольких тысяч ставить бессмысленно.&lt;br /&gt;
&lt;br /&gt;
В текущей версии системы реализован параллелизм с использованием OpenMP. Вместо OpenMP можно использовать любой метод многопоточной обработки данных, например, pthread. Сложность модификации кода минимальна, поскольку map/reduce подразумевает отсутствие зависимостей между различными блоками.&lt;br /&gt;
&lt;br /&gt;
При реализации распределенной системы можно размещать разные chunks на вычислительных узлах и агрегировать результаты. Из-за небольшого размера сообщений такую систему можно легко построить в ЦОД без использования специальных коммуникаций на обычных серверах.&lt;br /&gt;
&lt;br /&gt;
CUDA можно применять на этапе построения биометрического шаблона, что позволит значительно ускорить построение дескрипторов (например, во время добавления в базу большого числа изображений новых людей).&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
&lt;br /&gt;
В дальнейшем во всех тестах будет использоваться сервер с 2x E5-2683v3 128GB RAM. MOPS - миллионы операций (для map -скалярное произведение, reduce - сортировка) в секунду.&lt;br /&gt;
&lt;br /&gt;
Каждый тест проводится 20 раз, результаты усредняются.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Facerecognition-matcher.png|thumb|center|700px|Рисунок 1. Результаты работы map функции в зависимости от размера базы и числа потоков в openmp]]&lt;br /&gt;
&lt;br /&gt;
Т.к скорость чтения из DDR4 памяти 17GB/s (на практике немного меньше), то с 4 каналов памяти (по 2 на каждый процессор) нельзя считывать быстрее, чем 68GB/s. База 200M дескрипторов занимает 98GB ram, поэтому время 2300ms для вычисления всех скалярных произведений близко к нижней границе. Дальнейшее увеличение числа потоков на одном сервере не будет приводить к существенному ускорению работы программы.&lt;br /&gt;
&lt;br /&gt;
Результаты работы reduce функции в завсимости от размера базы и числа потоков в openmp:&lt;br /&gt;
[[Файл:Facerecognition_reduce.png|thumb|center|700px|Рисунок 2. Результаты работы reduce функции в зависимости от размера базы и числа потоков в openmp]]&lt;br /&gt;
&lt;br /&gt;
Reduce этап лучше распараллеливается, поскольку в нем намного меньше число обращений к памяти. Его также можно ускорять, например подбирая оптимальный размер блока (chunk size). Для базы в 200M лиц лучшая скорость 1400ms (достигается на 20 потоках, дальше ускорения нет).&lt;br /&gt;
&lt;br /&gt;
Значительное ускорение при размере базы в 100M (значение близко к 64GB) возникает предположительно из-за использование памяти второго процессора (суммарно 4 канала памяти, а не 2).&lt;br /&gt;
&lt;br /&gt;
[[Файл:Facerecognition_overall.png|thumb|center|700px|Рисунок 3. Суммарная скорость работы системы в зависимости от размера базы и числа потоков в openmp]]&lt;br /&gt;
&lt;br /&gt;
==== Исследование влияния HyperThreading на работу алгоритма ====&lt;br /&gt;
&lt;br /&gt;
Поскольку могут возникать проблемы из-за низкой пропускной способности памяти, можно предположить, что HyperThreading позволит ускорить работу программы. Во время ожидания данных из памяти может быть задействован второй вычислитель в ядре.&lt;br /&gt;
&lt;br /&gt;
Синяя точка на графике - лучший результат c HyperThreading, красная - HyperThreading выключен.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Facerecognition-ht-matcher.png|thumb|center|700px|Рисунок 4. Результаты работы map функции в зависимости от размера базы и числа потоков в openmp (10-56 потоков)]]&lt;br /&gt;
&lt;br /&gt;
[[Файл:Facerecognition-ht-reduce.png|thumb|center|700px|Рисунок 5. Результаты работы reduce функции в зависимости от размера базы и числа потоков в openmp (10-56 потоков)]]&lt;br /&gt;
&lt;br /&gt;
[[Файл:Facerecognition-ht-overall.png|thumb|center|700px|Рисунок 6. Суммарная скорость работы системы в зависимости от размера базы и числа потоков в openmp (10-56 потоков)]]&lt;br /&gt;
&lt;br /&gt;
Видно, что включение HyperThreading повышает производительность системы. Для reduce шага это ускорение значительно.&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Эксперименты проводились на сервере с 2x E5-2683v3 128GB RAM. &lt;br /&gt;
&lt;br /&gt;
Для семейства процессоров на ядре haswell возможно выполнение 32 операций умножения+сложения за такт.&lt;br /&gt;
&lt;br /&gt;
Поэтому пиковая производительность &amp;lt;math&amp;gt;Rpeak=2*14*32*2.0*10^9&amp;lt;/math&amp;gt;, где&lt;br /&gt;
* 2 - число процессоров&lt;br /&gt;
* 14 - количество ядер на каждом из процессоров&lt;br /&gt;
* 32 - количество операций за такт&lt;br /&gt;
* &amp;lt;math&amp;gt;2.0*10^9&amp;lt;/math&amp;gt; - частота ядра без turbo boost&lt;br /&gt;
&lt;br /&gt;
FLOPS алгоритма &amp;lt;math&amp;gt;k=100*10^6*128*2&amp;lt;/math&amp;gt;, где&lt;br /&gt;
* &amp;lt;math&amp;gt;100*10^6&amp;lt;/math&amp;gt; - число операций в секунду&lt;br /&gt;
* 128*2 - количество действий, необходимых для проведения одного сравнения&lt;br /&gt;
&lt;br /&gt;
Эффективность для map = k / peak = 0.014 (1.42%)&lt;br /&gt;
&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
&lt;br /&gt;
Данный алгоритм должен хорошо работать как на суперкомпьютерах со специализированной сетевой частью, так и на кластерах серверов с 1/10G Ethernet за счет низкой частоты обменов. Также при необходимость его можно использовать на мобильных рабочих станциях (ноутбуках) и специализированных серверах (4x xeon E7-8XXX), которые смогут обрабатывать в реальном времени большие объемы данных (например, биометрические для всех людей в стране).&lt;br /&gt;
&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Системы распознавания лиц редко бывают открытыми (или они низкого качества), поэтому известных распределенных систем распознавания лиц мало. Такие системы часто создаются под отдельный проект и их нельзя купить как &amp;quot;коробочное&amp;quot; решение.&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&lt;br /&gt;
[[Категория:Нейронные сети]]&lt;/div&gt;</summary>
		<author><name>Algoman</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%90%D1%80%D1%82%D0%B5%D0%BC_%D0%A2%D0%B0%D1%80%D0%B0%D0%BD/%D0%93%D1%80%D0%B0%D1%84%D0%BE-%D0%BE%D1%80%D0%B8%D0%B5%D0%BD%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_CHAMELEON&amp;diff=15532</id>
		<title>Участник:Артем Таран/Графо-ориентированный алгоритм кластеризации CHAMELEON</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%90%D1%80%D1%82%D0%B5%D0%BC_%D0%A2%D0%B0%D1%80%D0%B0%D0%BD/%D0%93%D1%80%D0%B0%D1%84%D0%BE-%D0%BE%D1%80%D0%B8%D0%B5%D0%BD%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_CHAMELEON&amp;diff=15532"/>
		<updated>2016-11-01T11:48:54Z</updated>

		<summary type="html">&lt;p&gt;Algoman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Algoman}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Графо-ориентированный алгоритм кластеризации CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n^2+nm+m^2log(m))&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n + log(n) + mlog(m) + m^2log(m))&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;\frac{n (n - 1)}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Статью подготовили: [[Участник:Артем_Таран|Артём Таран Иванович]] (разделы 1.1 - 1.10, 2.7), [[Участник:ShimchikN|Шимчик Никита Владимирович]] (разделы 1.1 - 1.10, 2.7).&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Кластеризация — многомерная статистическая процедура, выполняющая сбор данных, содержащих информацию о выборке объектов, и затем упорядочивающая объекты в сравнительно однородные группы (кластеры) с минимизацией межкластерного сходства и максимизацией внутрикластерного сходства.&lt;br /&gt;
&lt;br /&gt;
Графо-ориентированный алгоритм кластеризации CHAMELEON&amp;lt;ref name=&amp;quot;rt&amp;quot;&amp;gt;http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf&amp;lt;/ref&amp;gt; - алгоритм, который измеряет сходство двух кластеров на основе&lt;br /&gt;
динамической модели. В процессе кластеризации два кластера объединяются, только если показатели взаимосвязанности и близости между двумя кластерами являются высокими по отношению к показателям внутренней взаимосвязанности кластеров и близости элементов внутри этих кластеров. Процесс слияния с использованием динамической модели, использующийся в данном алгоритме облегчает открытие&lt;br /&gt;
природных и однородных кластеров. Методология динамического моделирования кластеров, использующаяся в CHAMELEON,&lt;br /&gt;
применима ко всем типам данных, для которых может быть построена матрица подобия.&lt;br /&gt;
&lt;br /&gt;
Алгоритм кластеризации CHAMELEON включает в себя три этапа:&lt;br /&gt;
&lt;br /&gt;
1) Построение графа, путём добавления рёбер по принципу k ближайших соседей.&lt;br /&gt;
&lt;br /&gt;
2) Выделение множества сравнительно малых связных подграфов.&lt;br /&gt;
&lt;br /&gt;
3) Формирование набора кластеров, на основе множества подграфов, полученных на предыдущем этапе.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Графы k ближайших соседей.jpg|1000px|thumb|center|Графы k ближайших соседей: 1) объекты в пространстве, 2) граф по принципу 1-го ближайшего соседа, 3) граф по принципу 2-го ближайшего соседа, 4) граф по принципу 3-х ближайших соседей&amp;lt;ref name=&amp;quot;rt&amp;quot;&amp;gt;http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf&amp;lt;/ref&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
==== Данные ====&lt;br /&gt;
* &#039;&#039;&#039;Исходные данные&#039;&#039;&#039;: множество из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; точек &amp;lt;math&amp;gt;V = \{v_{i}\}&amp;lt;/math&amp;gt; в метрическом пространстве, которое может быть задано в виде треугольной матрицы расстояний &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;n\times n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Промежуточный результат после первого этапа&#039;&#039;&#039;: граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, полученный путём соединения каждой точки с её &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайшими соседями.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Промежуточный результат после второго этапа&#039;&#039;&#039;: разбиение множества &amp;lt;math&amp;gt;V&amp;lt;/math&amp;gt; на набор &amp;lt;math&amp;gt;K = \{K_{i}\}&amp;lt;/math&amp;gt; попарно непересекающихся связных подмножеств, из которого образуется взвешенный граф &amp;lt;math&amp;gt;G_{2} = (K, E_{2})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Промежуточный результат после третьего этапа&#039;&#039;&#039;: итоговое разбиение множества вершин графа &amp;lt;math&amp;gt;G_{2}&amp;lt;/math&amp;gt; на набор кластеров &amp;lt;math&amp;gt;C = \{C_{i}\}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Вычисляемые данные&#039;&#039;&#039;: n-мерный вектор &amp;lt;math&amp;gt;v&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt;), показывающий отображение исходного множества точек на набор кластеров &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Определения ====&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Абсолютная взаимная связность между парой кластеров &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;&#039;&#039; определяется как сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; с вершинами из &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;. Эти ребра, фактически, входят в разделитель ребер графа, состоящего из кластеров &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;, и разбивающим его на подграфы &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;. Обозначается эта величина как&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Внутреннюю связность &amp;lt;math&amp;gt;EC_{C_{i}}&amp;lt;/math&amp;gt; кластера &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; можно вычислить как сумму ребер, входящих в разделитель ребер, разбивающий &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; на два совершенно равных подграфа.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Относительная взаимная &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; связность  пары кластеров &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;&#039;&#039; определяется формулой:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Учитывая значения относительной взаимной связности, можно добиться получения кластеров разного размера, формы и плотности, то есть общего внутреннего сходства.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Абсолютное взаимное сходство между парой кластеров &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;&#039;&#039; подсчитывается как среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; соответственно. Эти соединения обусловлены предыдущим разбиением общего графа, полученного на матрице сходства.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Относительное взаимное сходство &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; между парой кластеров &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;&#039;&#039; определяется как абсолютное сходство между этой парой кластеров, нормализованное с учетом их внутреннего сходства и вычисляется по формуле:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;S_{EC_{(C_{i})}}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;S_{EC_{(C_{i})}}&amp;lt;/math&amp;gt; - средние веса ребер (значения сходства), принадлежащих разделителю ребер кластеров &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; соответственно,&lt;br /&gt;
и &amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - средний вес ребер, соединяющих вершины &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; с вершинами &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;, причем ребра принадлежат разделителю ребер &amp;lt;math&amp;gt;EC_{(C_{i})}&amp;lt;/math&amp;gt;, определенному ранее.&lt;br /&gt;
&lt;br /&gt;
Далее, алгоритм применяет агломеративную иерархическую кластеризацию с использованием вышеозначенных показателей. Причем существует две стратегии их учета. Первая подразумевает наличие некоторых пороговых значений &amp;lt;math&amp;gt;T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;T_{RC}&amp;lt;/math&amp;gt;. В соответствии с этой стратегией, алгоритм для каждого кластера &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; проверяет, отвечают ли смежные (наиболее близкие) ему кластеры условиям:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} \geqslant T_{RI}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} \geqslant T_{RC}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если более одного смежного кластера отвечает этим условиям, то алгоритм выбирает для объединения наиболее связный кластер (граф), то есть такой кластер &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;, с которым у кластера &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; получается наибольшая абсолютная взаимная связность. По завершению прохода по всем кластерам, созданные таким образом пары объединяются. Параметры &amp;lt;math&amp;gt;T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;T_{RC}&amp;lt;/math&amp;gt; могут использоваться для изменения характеристик получаемых кластеров.&lt;br /&gt;
&lt;br /&gt;
Вторая стратегия заключается в использовании специальной функции, объединяющей понятия относительной взаимной связности и относительного взаимного сходства. На каждом шаге выбираются те кластеры для объединения, которые максимизируют эту функцию:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; выбирается пользователем. Если &amp;lt;math&amp;gt;\alpha &amp;gt; 1 &amp;lt;/math&amp;gt;, то алгоритм придает большее значение относительному взаимному сходству, а если &amp;lt;math&amp;gt;\alpha &amp;lt;  1 &amp;lt;/math&amp;gt;, то большее значение имеет относительная взаимная связность. Разумеется, данный подход позволяет получить полную дендрограмму кластерного анализа&amp;lt;ref name=&amp;quot;rty&amp;quot;&amp;gt;http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
&lt;br /&gt;
На первом этапе работы алгоритма вычислительным ядром можно считать процесс нахождения k ближайших соседей для каждой отдельной вершины.&lt;br /&gt;
&lt;br /&gt;
На втором этапе работы алгоритма вычислительным ядром является поиск разбиения графа на два подграфа с минимизацией разделителя рёбер графа.&lt;br /&gt;
&lt;br /&gt;
На третьем этапе работы алгоритма вычислительным ядром является расчёт &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; для пары смежных кластеров, а также их слияние.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап соответствует отдельному алгоритму. &lt;br /&gt;
&lt;br /&gt;
* Макрооперацией на первом этапе является процедура выделения k ближайших соседей.&lt;br /&gt;
&lt;br /&gt;
* Макрооперацией на втором этапе является процедура разбиения наибольшего подграфа на каждой итерации.&lt;br /&gt;
&lt;br /&gt;
* Макрооперациями на третьем этапе являются процедуры вычисления метрики для принятия решения об объединении кластеров и объединение кластеров на каждой итерации.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
* Первый этап (псевдокод):&lt;br /&gt;
  integer n; // Количество точек.&lt;br /&gt;
  integer k; // Параметр k&lt;br /&gt;
  integer A[n][n]; // Верхняя треугольная матрица расстояний между точками.&lt;br /&gt;
  &lt;br /&gt;
  integer E[n][n]; // Верхняя треугольная матрица рёбер графа G - изначально инициализирована нулями.&lt;br /&gt;
  foreach (integer i in (1,n-1) ) {&lt;br /&gt;
    integer Neighbors[k]; // матрица, используемая хранения ближайших соседей&lt;br /&gt;
    integer countN = 0;&lt;br /&gt;
    &lt;br /&gt;
    foreach (integer j in (i+1, n) ) {&lt;br /&gt;
      // Заполняем матрицу Neighbors, добавляя новые элементы и увеличивая счётчик countN.&lt;br /&gt;
      // Когда countN станет равен k, новые элементы будут вставляться на место старых, либо отбрасываться.&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    foreach (integer j in (0, countN) ) {&lt;br /&gt;
      E[min(i,j), max(i,j)] = 1;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  return E;&lt;br /&gt;
&lt;br /&gt;
* Второй этап:&lt;br /&gt;
  [[File:Диаграмма_шаг_2.png]]&lt;br /&gt;
&lt;br /&gt;
* Третий этап:&lt;br /&gt;
  [[File:Chameleon_stage_3.png|611px]]&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
1) Построение графа на основе метода k ближайших соседей в худшем случае требует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций;&lt;br /&gt;
&lt;br /&gt;
2) Для выделения множества сравнительно малых связных подграфов требуется &amp;lt;math&amp;gt;nm&amp;lt;/math&amp;gt; операций;&lt;br /&gt;
&lt;br /&gt;
3) Формирование набора кластеров, на основе множества подграфов, полученных на предыдущем этапе, требует &amp;lt;math&amp;gt;m^2log(m)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Итого, получаем последовательную сложность &amp;lt;math&amp;gt;O(n^2+nm+m^2log(m))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
&lt;br /&gt;
  [[File:Chameleon_inforgraph.png|811px]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Первый этап работы алгоритма можно распределить между &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; процессами: в этом случае каждому процессу назначается своя точка и происходит поиск &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей. Таким образом, его параллельная сложность составляет &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
На втором этапе количество задействованных процессов может варьироваться в зависимости от входных данных. В худшем случае число итераций можно оценить как &amp;lt;math&amp;gt;O(log(n))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
На третьем этапе можно распараллелить процесс расчёта метрик сходства между кластерами, однако итоговое слияние всё равно должно выполняться последовательно.&lt;br /&gt;
Поскольку процесс сравнения кластеров возможно распараллелить, сложность 3-го этапа составляет &amp;lt;math&amp;gt;mlog(m) + m^2log(m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Таким образом, суммарная параллельная сложность оказывается равна &amp;lt;math&amp;gt;O(n + log(n) + mlog(m) + m^2log(m))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
* Входные данные: &lt;br /&gt;
&lt;br /&gt;
1) Треугольная матрица &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;n\times n&amp;lt;/math&amp;gt; (где n — количество объектов), в которой элементу &amp;lt;math&amp;gt;a_{ij}&amp;lt;/math&amp;gt; соответствует расстояние между i-м и j-м объектами.&lt;br /&gt;
&lt;br /&gt;
2) Количество ближайших соседей &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; для вершин (рекомендуемое значение &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; от 5 до 20 в зависимости от количества анализируемых объектов).&lt;br /&gt;
&lt;br /&gt;
3) Наименьшее число вершин, которое может содержать наибольший подграф на 2-м этапе &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt;. Величина этого параметра варьируется от 1 до 5 % от общего числа объектов.&lt;br /&gt;
&lt;br /&gt;
* Объём входных данных: &amp;lt;math&amp;gt;\frac{n (n - 1)}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Выходные данные: n-мерный вектор &amp;lt;math&amp;gt;v&amp;lt;/math&amp;gt;, в котором элементу &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; соответствует номер кластера, присвоенный i-му объекту&lt;br /&gt;
&lt;br /&gt;
* Объём выходных данных: &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Первый этап алгоритма обладает хорошим ресурсом параллелизма: параллельная сложность его выполнения составляет &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;, что намного лучше последовательной оценки &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
У второго и третьего этапов алгоритма сложно полностью оценить ресурсы параллелизма. Но оба этапа возможно частично распараллелить.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вычислительную мощность&#039;&#039;&#039; для разных этапов алгоритма можно оценить как:&lt;br /&gt;
&lt;br /&gt;
1 этап: &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2 этап: &amp;lt;math&amp;gt;O(\frac{nm}{n^2+m^2})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3 этап: &amp;lt;math&amp;gt;O(\frac{m^2log(m)}{m^2+n})&amp;lt;/math&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью данного алгоритма является его недетерминированность. Несмотря на то, что 1-й этап детерминирован, алгоритм в целом является недетерминированным, так как на 2-ом этапе могут быть найдены различные разбиения на подграфы, а это повлияет и на итоговый результат работы алгоритма.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Существует несколько последовательных реализаций алгоритма. С одной из них можно ознакомиться по ссылке &amp;lt;ref name=&amp;quot;tra&amp;quot;&amp;gt;http://www.codeforge.com/article/192925&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, как, например METIS &amp;lt;ref name=&amp;quot;tru&amp;quot;&amp;gt;http://glaros.dtc.umn.edu/gkhome/metis/metis/overview&amp;lt;/ref&amp;gt; , hMETIS &amp;lt;ref name=&amp;quot;tri&amp;quot;&amp;gt;http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview&amp;lt;/ref&amp;gt; и RANN &amp;lt;ref name=&amp;quot;tro&amp;quot;&amp;gt;https://cran.r-project.org/web/packages/RANN/index.html&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь &amp;lt;ref name=&amp;quot;tr&amp;quot;&amp;gt;http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;/div&gt;</summary>
		<author><name>Algoman</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%90%D1%80%D1%82%D0%B5%D0%BC_%D0%A2%D0%B0%D1%80%D0%B0%D0%BD/%D0%93%D1%80%D0%B0%D1%84%D0%BE-%D0%BE%D1%80%D0%B8%D0%B5%D0%BD%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_CHAMELEON&amp;diff=15531</id>
		<title>Участник:Артем Таран/Графо-ориентированный алгоритм кластеризации CHAMELEON</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%90%D1%80%D1%82%D0%B5%D0%BC_%D0%A2%D0%B0%D1%80%D0%B0%D0%BD/%D0%93%D1%80%D0%B0%D1%84%D0%BE-%D0%BE%D1%80%D0%B8%D0%B5%D0%BD%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_CHAMELEON&amp;diff=15531"/>
		<updated>2016-11-01T11:48:36Z</updated>

		<summary type="html">&lt;p&gt;Algoman: Откат правок Algoman (обсуждение) к версии Артем Таран&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Графо-ориентированный алгоритм кластеризации CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n^2+nm+m^2log(m))&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n + log(n) + mlog(m) + m^2log(m))&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;\frac{n (n - 1)}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Статью подготовили: [[Участник:Артем_Таран|Артём Таран Иванович]] (разделы 1.1 - 1.10, 2.7), [[Участник:ShimchikN|Шимчик Никита Владимирович]] (разделы 1.1 - 1.10, 2.7).&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Кластеризация — многомерная статистическая процедура, выполняющая сбор данных, содержащих информацию о выборке объектов, и затем упорядочивающая объекты в сравнительно однородные группы (кластеры) с минимизацией межкластерного сходства и максимизацией внутрикластерного сходства.&lt;br /&gt;
&lt;br /&gt;
Графо-ориентированный алгоритм кластеризации CHAMELEON&amp;lt;ref name=&amp;quot;rt&amp;quot;&amp;gt;http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf&amp;lt;/ref&amp;gt; - алгоритм, который измеряет сходство двух кластеров на основе&lt;br /&gt;
динамической модели. В процессе кластеризации два кластера объединяются, только если показатели взаимосвязанности и близости между двумя кластерами являются высокими по отношению к показателям внутренней взаимосвязанности кластеров и близости элементов внутри этих кластеров. Процесс слияния с использованием динамической модели, использующийся в данном алгоритме облегчает открытие&lt;br /&gt;
природных и однородных кластеров. Методология динамического моделирования кластеров, использующаяся в CHAMELEON,&lt;br /&gt;
применима ко всем типам данных, для которых может быть построена матрица подобия.&lt;br /&gt;
&lt;br /&gt;
Алгоритм кластеризации CHAMELEON включает в себя три этапа:&lt;br /&gt;
&lt;br /&gt;
1) Построение графа, путём добавления рёбер по принципу k ближайших соседей.&lt;br /&gt;
&lt;br /&gt;
2) Выделение множества сравнительно малых связных подграфов.&lt;br /&gt;
&lt;br /&gt;
3) Формирование набора кластеров, на основе множества подграфов, полученных на предыдущем этапе.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Графы k ближайших соседей.jpg|1000px|thumb|center|Графы k ближайших соседей: 1) объекты в пространстве, 2) граф по принципу 1-го ближайшего соседа, 3) граф по принципу 2-го ближайшего соседа, 4) граф по принципу 3-х ближайших соседей&amp;lt;ref name=&amp;quot;rt&amp;quot;&amp;gt;http://www-users.cs.umn.edu/~han/dmclass/chameleon.pdf&amp;lt;/ref&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
==== Данные ====&lt;br /&gt;
* &#039;&#039;&#039;Исходные данные&#039;&#039;&#039;: множество из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; точек &amp;lt;math&amp;gt;V = \{v_{i}\}&amp;lt;/math&amp;gt; в метрическом пространстве, которое может быть задано в виде треугольной матрицы расстояний &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;n\times n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Промежуточный результат после первого этапа&#039;&#039;&#039;: граф &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt;, полученный путём соединения каждой точки с её &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайшими соседями.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Промежуточный результат после второго этапа&#039;&#039;&#039;: разбиение множества &amp;lt;math&amp;gt;V&amp;lt;/math&amp;gt; на набор &amp;lt;math&amp;gt;K = \{K_{i}\}&amp;lt;/math&amp;gt; попарно непересекающихся связных подмножеств, из которого образуется взвешенный граф &amp;lt;math&amp;gt;G_{2} = (K, E_{2})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Промежуточный результат после третьего этапа&#039;&#039;&#039;: итоговое разбиение множества вершин графа &amp;lt;math&amp;gt;G_{2}&amp;lt;/math&amp;gt; на набор кластеров &amp;lt;math&amp;gt;C = \{C_{i}\}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Вычисляемые данные&#039;&#039;&#039;: n-мерный вектор &amp;lt;math&amp;gt;v&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt;), показывающий отображение исходного множества точек на набор кластеров &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Определения ====&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Абсолютная взаимная связность между парой кластеров &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;&#039;&#039; определяется как сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; с вершинами из &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;. Эти ребра, фактически, входят в разделитель ребер графа, состоящего из кластеров &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;, и разбивающим его на подграфы &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;. Обозначается эта величина как&lt;br /&gt;
&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Внутреннюю связность &amp;lt;math&amp;gt;EC_{C_{i}}&amp;lt;/math&amp;gt; кластера &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; можно вычислить как сумму ребер, входящих в разделитель ребер, разбивающий &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; на два совершенно равных подграфа.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Относительная взаимная &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; связность  пары кластеров &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;&#039;&#039; определяется формулой:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{2*|EC_{(C_{i},C_{j})}|}{|EC_{C_{i}}|+|EC_{C_{j}}|}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Учитывая значения относительной взаимной связности, можно добиться получения кластеров разного размера, формы и плотности, то есть общего внутреннего сходства.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Абсолютное взаимное сходство между парой кластеров &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;&#039;&#039; подсчитывается как среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; соответственно. Эти соединения обусловлены предыдущим разбиением общего графа, полученного на матрице сходства.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;Относительное взаимное сходство &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; между парой кластеров &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;&#039;&#039; определяется как абсолютное сходство между этой парой кластеров, нормализованное с учетом их внутреннего сходства и вычисляется по формуле:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;S_{EC_{(C_{i})}}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;S_{EC_{(C_{i})}}&amp;lt;/math&amp;gt; - средние веса ребер (значения сходства), принадлежащих разделителю ребер кластеров &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt; соответственно,&lt;br /&gt;
и &amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - средний вес ребер, соединяющих вершины &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; с вершинами &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;, причем ребра принадлежат разделителю ребер &amp;lt;math&amp;gt;EC_{(C_{i})}&amp;lt;/math&amp;gt;, определенному ранее.&lt;br /&gt;
&lt;br /&gt;
Далее, алгоритм применяет агломеративную иерархическую кластеризацию с использованием вышеозначенных показателей. Причем существует две стратегии их учета. Первая подразумевает наличие некоторых пороговых значений &amp;lt;math&amp;gt;T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;T_{RC}&amp;lt;/math&amp;gt;. В соответствии с этой стратегией, алгоритм для каждого кластера &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; проверяет, отвечают ли смежные (наиболее близкие) ему кластеры условиям:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} \geqslant T_{RI}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} \geqslant T_{RC}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если более одного смежного кластера отвечает этим условиям, то алгоритм выбирает для объединения наиболее связный кластер (граф), то есть такой кластер &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;, с которым у кластера &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; получается наибольшая абсолютная взаимная связность. По завершению прохода по всем кластерам, созданные таким образом пары объединяются. Параметры &amp;lt;math&amp;gt;T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;T_{RC}&amp;lt;/math&amp;gt; могут использоваться для изменения характеристик получаемых кластеров.&lt;br /&gt;
&lt;br /&gt;
Вторая стратегия заключается в использовании специальной функции, объединяющей понятия относительной взаимной связности и относительного взаимного сходства. На каждом шаге выбираются те кластеры для объединения, которые максимизируют эту функцию:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; выбирается пользователем. Если &amp;lt;math&amp;gt;\alpha &amp;gt; 1 &amp;lt;/math&amp;gt;, то алгоритм придает большее значение относительному взаимному сходству, а если &amp;lt;math&amp;gt;\alpha &amp;lt;  1 &amp;lt;/math&amp;gt;, то большее значение имеет относительная взаимная связность. Разумеется, данный подход позволяет получить полную дендрограмму кластерного анализа&amp;lt;ref name=&amp;quot;rty&amp;quot;&amp;gt;http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
&lt;br /&gt;
На первом этапе работы алгоритма вычислительным ядром можно считать процесс нахождения k ближайших соседей для каждой отдельной вершины.&lt;br /&gt;
&lt;br /&gt;
На втором этапе работы алгоритма вычислительным ядром является поиск разбиения графа на два подграфа с минимизацией разделителя рёбер графа.&lt;br /&gt;
&lt;br /&gt;
На третьем этапе работы алгоритма вычислительным ядром является расчёт &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;RC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; для пары смежных кластеров, а также их слияние.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Алгоритм CHAMELEON выполняется в 3 этапа, последовательных относительно друг друга. Каждый этап соответствует отдельному алгоритму. &lt;br /&gt;
&lt;br /&gt;
* Макрооперацией на первом этапе является процедура выделения k ближайших соседей.&lt;br /&gt;
&lt;br /&gt;
* Макрооперацией на втором этапе является процедура разбиения наибольшего подграфа на каждой итерации.&lt;br /&gt;
&lt;br /&gt;
* Макрооперациями на третьем этапе являются процедуры вычисления метрики для принятия решения об объединении кластеров и объединение кластеров на каждой итерации.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
* Первый этап (псевдокод):&lt;br /&gt;
  integer n; // Количество точек.&lt;br /&gt;
  integer k; // Параметр k&lt;br /&gt;
  integer A[n][n]; // Верхняя треугольная матрица расстояний между точками.&lt;br /&gt;
  &lt;br /&gt;
  integer E[n][n]; // Верхняя треугольная матрица рёбер графа G - изначально инициализирована нулями.&lt;br /&gt;
  foreach (integer i in (1,n-1) ) {&lt;br /&gt;
    integer Neighbors[k]; // матрица, используемая хранения ближайших соседей&lt;br /&gt;
    integer countN = 0;&lt;br /&gt;
    &lt;br /&gt;
    foreach (integer j in (i+1, n) ) {&lt;br /&gt;
      // Заполняем матрицу Neighbors, добавляя новые элементы и увеличивая счётчик countN.&lt;br /&gt;
      // Когда countN станет равен k, новые элементы будут вставляться на место старых, либо отбрасываться.&lt;br /&gt;
    }&lt;br /&gt;
  &lt;br /&gt;
    foreach (integer j in (0, countN) ) {&lt;br /&gt;
      E[min(i,j), max(i,j)] = 1;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  return E;&lt;br /&gt;
&lt;br /&gt;
* Второй этап:&lt;br /&gt;
  [[File:Диаграмма_шаг_2.png]]&lt;br /&gt;
&lt;br /&gt;
* Третий этап:&lt;br /&gt;
  [[File:Chameleon_stage_3.png|611px]]&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
1) Построение графа на основе метода k ближайших соседей в худшем случае требует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций;&lt;br /&gt;
&lt;br /&gt;
2) Для выделения множества сравнительно малых связных подграфов требуется &amp;lt;math&amp;gt;nm&amp;lt;/math&amp;gt; операций;&lt;br /&gt;
&lt;br /&gt;
3) Формирование набора кластеров, на основе множества подграфов, полученных на предыдущем этапе, требует &amp;lt;math&amp;gt;m^2log(m)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Итого, получаем последовательную сложность &amp;lt;math&amp;gt;O(n^2+nm+m^2log(m))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
&lt;br /&gt;
  [[File:Chameleon_inforgraph.png|811px]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Первый этап работы алгоритма можно распределить между &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; процессами: в этом случае каждому процессу назначается своя точка и происходит поиск &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей. Таким образом, его параллельная сложность составляет &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
На втором этапе количество задействованных процессов может варьироваться в зависимости от входных данных. В худшем случае число итераций можно оценить как &amp;lt;math&amp;gt;O(log(n))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
На третьем этапе можно распараллелить процесс расчёта метрик сходства между кластерами, однако итоговое слияние всё равно должно выполняться последовательно.&lt;br /&gt;
Поскольку процесс сравнения кластеров возможно распараллелить, сложность 3-го этапа составляет &amp;lt;math&amp;gt;mlog(m) + m^2log(m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Таким образом, суммарная параллельная сложность оказывается равна &amp;lt;math&amp;gt;O(n + log(n) + mlog(m) + m^2log(m))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
* Входные данные: &lt;br /&gt;
&lt;br /&gt;
1) Треугольная матрица &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;n\times n&amp;lt;/math&amp;gt; (где n — количество объектов), в которой элементу &amp;lt;math&amp;gt;a_{ij}&amp;lt;/math&amp;gt; соответствует расстояние между i-м и j-м объектами.&lt;br /&gt;
&lt;br /&gt;
2) Количество ближайших соседей &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; для вершин (рекомендуемое значение &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; от 5 до 20 в зависимости от количества анализируемых объектов).&lt;br /&gt;
&lt;br /&gt;
3) Наименьшее число вершин, которое может содержать наибольший подграф на 2-м этапе &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt;. Величина этого параметра варьируется от 1 до 5 % от общего числа объектов.&lt;br /&gt;
&lt;br /&gt;
* Объём входных данных: &amp;lt;math&amp;gt;\frac{n (n - 1)}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Выходные данные: n-мерный вектор &amp;lt;math&amp;gt;v&amp;lt;/math&amp;gt;, в котором элементу &amp;lt;math&amp;gt;v_{i}&amp;lt;/math&amp;gt; соответствует номер кластера, присвоенный i-му объекту&lt;br /&gt;
&lt;br /&gt;
* Объём выходных данных: &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Первый этап алгоритма обладает хорошим ресурсом параллелизма: параллельная сложность его выполнения составляет &amp;lt;math&amp;gt;O(n)&amp;lt;/math&amp;gt;, что намного лучше последовательной оценки &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
У второго и третьего этапов алгоритма сложно полностью оценить ресурсы параллелизма. Но оба этапа возможно частично распараллелить.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вычислительную мощность&#039;&#039;&#039; для разных этапов алгоритма можно оценить как:&lt;br /&gt;
&lt;br /&gt;
1 этап: &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2 этап: &amp;lt;math&amp;gt;O(\frac{nm}{n^2+m^2})&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3 этап: &amp;lt;math&amp;gt;O(\frac{m^2log(m)}{m^2+n})&amp;lt;/math&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;b&amp;gt;Детерминированность:&amp;lt;/b&amp;gt; Важной особенностью данного алгоритма является его недетерминированность. Несмотря на то, что 1-й этап детерминирован, алгоритм в целом является недетерминированным, так как на 2-ом этапе могут быть найдены различные разбиения на подграфы, а это повлияет и на итоговый результат работы алгоритма.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Существует несколько последовательных реализаций алгоритма. С одной из них можно ознакомиться по ссылке &amp;lt;ref name=&amp;quot;tra&amp;quot;&amp;gt;http://www.codeforge.com/article/192925&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Возможна реализация алгоритма CHAMELEON с использованием графовых библиотек, как, например METIS &amp;lt;ref name=&amp;quot;tru&amp;quot;&amp;gt;http://glaros.dtc.umn.edu/gkhome/metis/metis/overview&amp;lt;/ref&amp;gt; , hMETIS &amp;lt;ref name=&amp;quot;tri&amp;quot;&amp;gt;http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview&amp;lt;/ref&amp;gt; и RANN &amp;lt;ref name=&amp;quot;tro&amp;quot;&amp;gt;https://cran.r-project.org/web/packages/RANN/index.html&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON найдено не было. Однако существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь &amp;lt;ref name=&amp;quot;tr&amp;quot;&amp;gt;http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;/div&gt;</summary>
		<author><name>Algoman</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%90%D1%80%D1%82%D0%B5%D0%BC_%D0%A2%D0%B0%D1%80%D0%B0%D0%BD&amp;diff=15530</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%90%D1%80%D1%82%D0%B5%D0%BC_%D0%A2%D0%B0%D1%80%D0%B0%D0%BD&amp;diff=15530"/>
		<updated>2016-11-01T11:48:25Z</updated>

		<summary type="html">&lt;p&gt;Algoman: Отмена правки 15092, сделанной участником Algoman (обс.)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Замечания к [[Участник:Артем_Таран/Графо-ориентированный_алгоритм_кластеризации_CHAMELEON]] ==&lt;br /&gt;
&lt;br /&gt;
1) отсутствует оценка вычислительной мощности алгоритма в п 1.10&lt;/div&gt;</summary>
		<author><name>Algoman</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%90%D1%80%D1%82%D0%B5%D0%BC_%D0%A2%D0%B0%D1%80%D0%B0%D0%BD&amp;diff=15528</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%90%D1%80%D1%82%D0%B5%D0%BC_%D0%A2%D0%B0%D1%80%D0%B0%D0%BD&amp;diff=15528"/>
		<updated>2016-11-01T11:48:19Z</updated>

		<summary type="html">&lt;p&gt;Algoman: Отмена правки 15093, сделанной участником Algoman (обс.)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Замечания к [[Участник:Артем_Таран/Графо-ориентированный_алгоритм_кластеризации_CHAMELEON]] ==&lt;br /&gt;
&lt;br /&gt;
1) отсутствует оценка вычислительной мощности алгоритма в п 1.10&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Замечения от 31.10&lt;br /&gt;
&lt;br /&gt;
отсутсвует ссылка на источник картинки&lt;br /&gt;
&amp;quot;- В конце статьи должен быть приведен список всех источников, откуда бралась информация по алгоритму. Если вы используется готовый рисунок, то сслыку на источник нужно разместить либо в подписи к рисунку, либо в тексте, где стоит ссылка на рисунок.&amp;quot;&lt;/div&gt;</summary>
		<author><name>Algoman</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%90%D0%BB%D0%B5%D0%BA%D1%81%D0%B0%D0%BD%D0%B4%D1%80_%D0%9A%D1%83%D0%B2%D0%B0%D0%B5%D0%B2/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8,_%D0%BE%D1%81%D0%BD%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9_%D0%BD%D0%B0_%D0%BC%D0%B0%D0%BA%D1%81%D0%B8%D0%BC%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BE%D0%B6%D0%B8%D0%B4%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=15487</id>
		<title>Участник:Александр Куваев/Алгоритм кластеризации, основанный на максимизации ожидания</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%90%D0%BB%D0%B5%D0%BA%D1%81%D0%B0%D0%BD%D0%B4%D1%80_%D0%9A%D1%83%D0%B2%D0%B0%D0%B5%D0%B2/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8,_%D0%BE%D1%81%D0%BD%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9_%D0%BD%D0%B0_%D0%BC%D0%B0%D0%BA%D1%81%D0%B8%D0%BC%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BE%D0%B6%D0%B8%D0%B4%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=15487"/>
		<updated>2016-11-01T10:45:25Z</updated>

		<summary type="html">&lt;p&gt;Algoman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Algoman}}&lt;br /&gt;
&lt;br /&gt;
Авторы описания:&lt;br /&gt;
* Куваев А.С., группа 620 (математическая постановка задачи, схема реализации алгоритма, оценка сложности, описание ресурса параллелизма)&lt;br /&gt;
* Щенявская Е.В., группа 616 (описание алгоритма, визуализация информационного графа и примера работы алгоритма, описание свойств алгоритма)&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритмов ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
Задача кластеризации заключается в разбиении входного множества объектов на непересекающиеся подмножества, называемые кластерами, так, чтобы каждый кластер состоял из схожих объектов, а объекты разных кластеров существенно отличались друг от друга&amp;lt;ref name=vorontsov&amp;gt;Воронцов К.В., Математические методы обучения по прецедентам.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Решение этой задачи принципиально неоднозначно по следующим причинам&amp;lt;ref name=vorontsov/&amp;gt;:&lt;br /&gt;
# результат кластеризации зависит от способа задания меры сходства объектов выборки&lt;br /&gt;
# не существует однозначно наилучшего критерия качества кластеризации&lt;br /&gt;
# число кластеров, как правило, неизвестно заранее и задается из некоторых априорных соображений (хотя существуют алгоритмы, способные определять число кластеров автоматически)&lt;br /&gt;
&lt;br /&gt;
По описанной выше причине существует большое число алгоритмов кластеризации, приводящих к различным разбиениям исходного множества объектов. На этой странице представлено описание одного из таких методов — EM-алгоритма. EM-алгоритм опирается на предположение о вероятностной природе данных: элементы выборки получены случайно и независимо из смеси распределений с фиксированным числом компонент &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;. Таким образом, плотность распределения на множестве объектов имеет следующий вид:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;p(x)=\sum_{j=1}^{k}w_{j}p_{j}(x), \ \sum_{j=1}^{k}w_{j}=1, \ w_{j} \ge 0 &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;p_{j}&amp;lt;/math&amp;gt; - плотность распределения &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-й компоненты смеси (кластера).&lt;br /&gt;
&lt;br /&gt;
Везде в дальнейшем будем предполагать, что &amp;lt;math&amp;gt;p_{j}&amp;lt;/math&amp;gt; имеют вид многомерных нормальных плотностей с произвольной матрицей ковариации: смеси нормальных распределений позволяют аппроксимировать произвольные непрерывные функции плотности с наперед заданной точностью&amp;lt;ref name=korolev&amp;gt;Королёв В.Ю., ЕМ-алгоритм, его модификации и их применение к задаче разделения смесей вероятностных распределений. Теоретический обзор. - М.: ИПИРАН, 2007.&amp;lt;/ref&amp;gt;. Результатом работы EM-алгоритма являются оценки априорных вероятностей компонент смеси &amp;lt;math&amp;gt;w_{j}&amp;lt;/math&amp;gt;, а также оценки векторов математических ожиданий и матриц ковариаций для каждой компоненты. Зная параметры распределения смеси, каждому объекту будет сопоставляться тот кластер, вероятность принадлежности к которому будет максимальной.&lt;br /&gt;
&lt;br /&gt;
EM-алгоритм позволяет значительно упростить задачу максимизации правдоподобия выборки путем искусственного введения вспомогательной матрицы скрытых переменных &amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt;. Алгоритм заключается в последовательном повторении шагов E(expectation) и M(maximization):&lt;br /&gt;
* На шаге E на основе текущего приближения параметров смеси по формуле Байеса вычисляются ожидаемые значения скрытых переменных &amp;lt;math&amp;gt;g_{ij}&amp;lt;/math&amp;gt; — апостериорные вероятности того, что &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-й объект принадлежит кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;.&lt;br /&gt;
* На шаге M решается задача максимизации правдоподобия для нахождения следующего приближения параметров смеси на основе текущего приближения и матрицы скрытых переменных, при этом решение этой задачи выписывается в явном виде.&lt;br /&gt;
&lt;br /&gt;
[[File:EM iterations.png|thumb|center|800px|Рисунок 1. Визуализация компонент смеси после некоторых итераций алгоритма в двумерном пространстве признаков. Для каждой компоненты эллипсами выделены доверительные области с уровнями доверия 0.9, 0.95 и 0.99.]]&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
Пусть заданы &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; объектов &amp;lt;math&amp;gt;x_{1},\dotsc,x_{l}&amp;lt;/math&amp;gt;, каждый из которых описывается &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; числовыми признаками. Таким образом, определена матрица объектов-признаков &amp;lt;math&amp;gt;X \in \R^{l \times n}.&amp;lt;/math&amp;gt; Предполагается, что объекты выбраны случайно и независимо из смеси &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;-мерных нормальных распределений с фиксированным числом компонент &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;. Плотность распределения на множестве объектов имеет вид:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;p(x)=\sum_{j=1}^{k}w_{j}p_{j}(x), \ \sum_{j=1}^{k}w_{j}=1, \ w_{j} \ge 0 &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;p_{j}&amp;lt;/math&amp;gt; - плотность распределения &amp;lt;math&amp;gt;j&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;\mu_{j}&amp;lt;/math&amp;gt; и матрицей ковариаций &amp;lt;math&amp;gt;\Sigma_{j}&amp;lt;/math&amp;gt; порядка &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;j = 1,\dotsc,k&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; матрица объектов-признаков &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt;, число кластеров &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;, максимальное число итераций &amp;lt;math&amp;gt;imax&amp;lt;/math&amp;gt;, минимальная величина изменения логарифма правдоподобия &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; набор оценок весов, математических ожиданий и ковариационных матриц компонент смеси &amp;lt;math&amp;gt;\theta = (w_{1},...,w_{k}; \; \mu_{1},...,\mu_{k}; \; \Sigma_{1},...,\Sigma_{k})&amp;lt;/math&amp;gt;, максимизирующий правдоподобие выборки.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Структура алгоритма:&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Инициализация параметров:&#039;&#039;&#039; существует большое число вариантов инициализации параметров распределения. Один из возможных подходов — задание векторов математических ожиданий компонент случайными элементами выборки, задание матриц ковариаций единичными матрицами и задание весов компонент равными &amp;lt;math&amp;gt;\frac{1}{k}.&amp;lt;/math&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Последовательное выполнение шагов E и M&#039;&#039;&#039; до тех пор, пока правдоподобие выборки не стабилизируется или не будет достигнуто максимальное число итераций:&lt;br /&gt;
** &#039;&#039;&#039;Шаг E:&#039;&#039;&#039; вычисление значений скрытых переменных по формуле Байеса:&lt;br /&gt;
*:&amp;lt;math&amp;gt;g_{ij} = \frac{w_{j} p_{j}(x_{i})}{\sum_{s=1}^{k} w_{s} p_{s}(x_{i})}&amp;lt;/math&amp;gt; , где &amp;lt;math&amp;gt;p_{j}(x_{i}) = \frac{1}{(2\pi)^{n/2}\sqrt{|\Sigma_{j}|}} \exp \biggl( -\frac{1}{2}(x_{i} - \mu_{j})^{T} \Sigma_{j}^{-1} (x_{i} - \mu_{j}) \biggr), \ i = 1,\dotsc,l; \ j = 1,\dotsc,k &amp;lt;/math&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Шаг M:&#039;&#039;&#039; перерасчет параметров смеси на основе текущего приближения и матрицы скрытых переменных:&lt;br /&gt;
*:&amp;lt;math&amp;gt;w_{j} = \frac{1}{l} \sum_{i=1}^{l} g_{ij}, \ j = 1,\dotsc,k;&amp;lt;/math&amp;gt;&lt;br /&gt;
*:&amp;lt;math&amp;gt;\mu_{j} = \frac{1}{l w_{j}} \sum_{i=1}^{l} g_{ij} x_{i}, \ j = 1,\dotsc,k;&amp;lt;/math&amp;gt;&lt;br /&gt;
*:&amp;lt;math&amp;gt;\Sigma_{j} = \frac{1}{l w_{j}} \sum_{i=1}^{l} g_{ij}(x_{i} - \mu_{j})(x_{i} - \mu_{j})^T, \ j = 1,\dotsc,k.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро EM-алгоритма — процедура последовательного выполнения шагов E и M:&lt;br /&gt;
* На шаге E на основе текущего приближения параметров смеси вычисляются ожидаемые значения скрытых переменных&lt;br /&gt;
* На шаге M вычисляется следующее приближение параметров смеси на основе текущего приближения и матрицы скрытых переменных&lt;br /&gt;
Наиболее трудоемкой операцией с вычислительной точки зрения является шаг E, в ходе которого производится обращение ковариационных матриц, вычисление их определителей, а также многократное перемножение векторов и матриц при вычислении скрытых переменных.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм состоит из двух итерационно проводимых макроопераций: E-шага и M-шага.&lt;br /&gt;
&lt;br /&gt;
В ходе E-шага используется:&lt;br /&gt;
* Обращение ковариационной матрицы и вычисление ее определителя&lt;br /&gt;
* Умножение вектор-строки на матрицу и вектор-строки на вектор-столбец &lt;br /&gt;
В ходе M-шага используется:&lt;br /&gt;
* Умножение вектор-столбца на вектор-строку&lt;br /&gt;
* Взвешенное суммирование векторов и матриц &lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
# Для всех &amp;lt;math&amp;gt;j = 1,\dotsc,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
#: Инициализировать &amp;lt;math&amp;gt;w_{j}, \ \mu_{j}, \ \Sigma_{j}&amp;lt;/math&amp;gt;&lt;br /&gt;
# Для всех &amp;lt;math&amp;gt;iter = 1,\dotsc,imax&amp;lt;/math&amp;gt;:&lt;br /&gt;
## Шаг E:&lt;br /&gt;
##: Для всех &amp;lt;math&amp;gt;j = 1,\dotsc,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
##:: Вычислить &amp;lt;math&amp;gt;|\Sigma_{j}|, \ \Sigma_{j}^{-1}&amp;lt;/math&amp;gt;&lt;br /&gt;
##: Для всех &amp;lt;math&amp;gt;i = 1,\dotsc,l&amp;lt;/math&amp;gt;:&lt;br /&gt;
##:: &amp;lt;math&amp;gt;sum = 0&amp;lt;/math&amp;gt;&lt;br /&gt;
##:: Для всех &amp;lt;math&amp;gt;j = 1,\dotsc,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
##::: Вычислить &amp;lt;math&amp;gt;p_{j}(x_{i}) = \frac{1}{(2\pi)^{n/2}\sqrt{|\Sigma_{j}|}} \exp \biggl( -\frac{1}{2}(x_{i} - \mu_{j})^{T} \Sigma_{j}^{-1} (x_{i} - \mu_{j}) \biggr)&amp;lt;/math&amp;gt;&lt;br /&gt;
##::: &amp;lt;math&amp;gt;sum = sum + w_{j}p_{j}(x_{i})&amp;lt;/math&amp;gt;&lt;br /&gt;
##:: Для всех &amp;lt;math&amp;gt;j = 1,\dotsc,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
##::: Вычислить &amp;lt;math&amp;gt;g_{ij} = \frac{w_{j} p_{j}(x_{i})}{sum}&amp;lt;/math&amp;gt;&lt;br /&gt;
## Шаг M:&lt;br /&gt;
##: Для всех &amp;lt;math&amp;gt;j = 1,\dotsc,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
##:: Вычислить &amp;lt;math&amp;gt;w_{j} = \frac{1}{l} \sum_{i=1}^{l} g_{ij}&amp;lt;/math&amp;gt;&lt;br /&gt;
##:: Вычислить &amp;lt;math&amp;gt;\mu_{j} = \frac{1}{l w_{j}} \sum_{i=1}^{l} g_{ij} x_{i}&amp;lt;/math&amp;gt;&lt;br /&gt;
##:: Вычислить &amp;lt;math&amp;gt;\Sigma_{j} = \frac{1}{l w_{j}} \sum_{i=1}^{l} g_{ij}(x_{i} - \mu_{j})(x_{i} - \mu_{j})^T&amp;lt;/math&amp;gt;&lt;br /&gt;
## Вычислить изменения логарифма правдоподобия &amp;lt;math&amp;gt;\Delta&amp;lt;/math&amp;gt;&lt;br /&gt;
## Если &amp;lt;math&amp;gt;\Delta &amp;lt; \varepsilon&amp;lt;/math&amp;gt;, то досрочно выйти из цикла&lt;br /&gt;
# Вернуть &amp;lt;math&amp;gt;w_{j}, \mu_{j}, \Sigma_{j}, \ j = 1,\dotsc,k.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
Рассмотрим мультипликативную сложность одной итерации алгоритма:&lt;br /&gt;
* &#039;&#039;&#039;E-шаг:&#039;&#039;&#039;&lt;br /&gt;
** Сложность обращения матрицы ковариаций и вычисления ее определителя — &amp;lt;math&amp;gt;O(n^{3})&amp;lt;/math&amp;gt; (для простоты будем рассматривать метод Гаусса)&lt;br /&gt;
** Сложность вычисления расстояния Махаланобиса (показателя экспоненты) при вычислении значения каждой скрытой переменной — &amp;lt;math&amp;gt;O(n^{2})&amp;lt;/math&amp;gt;&lt;br /&gt;
** Общая сложность E-шага — &amp;lt;math&amp;gt;O(k * n^{3} + k * l * n^{2})&amp;lt;/math&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;M-шаг:&#039;&#039;&#039;&lt;br /&gt;
** Сложность пересчета веса кластера — &amp;lt;math&amp;gt;O(l)&amp;lt;/math&amp;gt;&lt;br /&gt;
** Сложность пересчета центра кластера — &amp;lt;math&amp;gt;O(l * n)&amp;lt;/math&amp;gt;&lt;br /&gt;
** Сложность пересчета матрицы ковариаций кластера — &amp;lt;math&amp;gt;O(l * n)&amp;lt;/math&amp;gt;&lt;br /&gt;
** Общая сложность M-шага — &amp;lt;math&amp;gt;O(k * l * n)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Таким образом, общая сложность одной итерации — &amp;lt;math&amp;gt;O(k * n^{2} * (l + n))&amp;lt;/math&amp;gt;. При учете ограничения на максимальное число итераций получим оценку общей сложности алгоритма — &amp;lt;math&amp;gt;O(imax * k * n^{2} * (l + n))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Большое влияние на сложность E-шага оказывает необходимость обращать ковариационные матрицы и вычислять их определители. Помимо того, что это трудоемкая операция, ковариационные матрицы могут оказаться плохо обусловленными, что может привести к неустойчивости выборочных оценок параметров смеси. Обращения матриц можно избежать, если принять гипотезу о том, что в каждой компоненте смеси признаки некоррелированы, то есть ковариационные матрицы диагональные. В таком случае общая сложность алгоритма составит &amp;lt;math&amp;gt;O(imax * k * n * l)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
На рисунках 2 и 3 представлены информационные графы&amp;lt;ref name=voevodin&amp;gt;Воеводин В.В., Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&amp;lt;/ref&amp;gt; шагов E и M соответственно. Прямоугольниками обозначены входные данные (с пометкой in/out), эллипсами обозначены операции, производимые над данными согласно алгоритму.&lt;br /&gt;
&lt;br /&gt;
Как видно из рисунка 2, E-шаг распадается на:&lt;br /&gt;
* Обращение матриц ковариаций и вычисление их определителей&lt;br /&gt;
* Независимый расчет скрытых переменных по каждому объекту&lt;br /&gt;
&lt;br /&gt;
[[File:E-step.png|thumb|center|1100px|Рисунок 2. Граф шага E с отображением входных и выходных данных.]]&lt;br /&gt;
&lt;br /&gt;
На рисунке 3 видно, что некоторые промежуточные вычисления на шаге M можно проводить независимо для каждого объекта, но после этого придется проводить агрегацию полученных результатов по кластерам.&lt;br /&gt;
&lt;br /&gt;
[[File:M-step.png|thumb|center|1100px|Рисунок 3. Граф шага M с отображением входных и выходных данных.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
Из информационных графов на рисунках 2 и 3 видно, что:&lt;br /&gt;
* Шаг E — наиболее ресурсоемкий этап алгоритма — эффективно распараллеливается по объектам после предварительного обращения матриц ковариаций и вычисления их определителей: при расчете скрытых переменных для фиксированного объекта информация о других объектах не используется. Также стоит отметить, что для всех объектов выполняется одна и та же последовательность действий. Таким образом, параллельная сложность E-шага — &amp;lt;math&amp;gt;O(k * n^{2})&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Менее ресурсоемкий шаг M распараллеливается хуже: промежуточные вычисления можно проводить независимо для каждого объекта, но после этого придется проводить агрегацию полученных результатов по кластерам.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; плотная матрица объектов-признаков &amp;lt;math&amp;gt;X \in \R^{l \times n}&amp;lt;/math&amp;gt;, число кластеров &amp;lt;math&amp;gt;k \in \N&amp;lt;/math&amp;gt;, максимальное число итераций &amp;lt;math&amp;gt;imax \in \N&amp;lt;/math&amp;gt;, минимальная величина изменения логарифма правдоподобия &amp;lt;math&amp;gt;\varepsilon \in \R&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;ln + 3&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; вещественный вектор весов &amp;lt;math&amp;gt;w \in \R^{k}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; вещественных векторов математических ожиданий &amp;lt;math&amp;gt;\mu_{j} \in \R^{n}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; вещественных ковариационных матриц &amp;lt;math&amp;gt;\Sigma_{j} \in \R^{n \times n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;k(n^{2}+n+1)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
Вычислительная мощность EM-алгоритма в предположении о том, что &amp;lt;math&amp;gt;l \gg n&amp;lt;/math&amp;gt; (это условие выполняется в подавляющем большинстве прикладных задач), оценивается величиной &amp;lt;math&amp;gt;O(imax * k * n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Достоинства EM-алгоритма:&lt;br /&gt;
* Мощная математическая основа&lt;br /&gt;
* Слабая чувствительность к выбросам&lt;br /&gt;
* Быстрая сходимость при удачной инициализации параметров&lt;br /&gt;
* Линейный рост сложности при увеличении количества объектов&lt;br /&gt;
&lt;br /&gt;
Недостатки EM-алгоритма:&lt;br /&gt;
* В классическом варианте не может самостоятельно определить количество компонент смеси&lt;br /&gt;
* Трудоемкий и неустойчивый процесс обращения матриц ковариаций в случае несферических компонент смеси&lt;br /&gt;
* Не является детерминированным: в начале работы происходит инициализация начальных параметров случайным образом&lt;br /&gt;
* Не является устойчивым: результат работы сильно зависит от инициализации параметров. При неудачной инициализации может обладать низкой скоростью сходимости, может сойтись к локальному экстремуму или не сойтись вовсе&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
# [http://scikit-learn.org/stable/modules/generated/sklearn.mixture.GaussianMixture.html#sklearn.mixture.GaussianMixture scikit-learn(Python)]&lt;br /&gt;
# [http://docs.opencv.org/2.4/modules/ml/doc/expectation_maximization.html OpenCV(C++/Python)]&lt;br /&gt;
# [http://www.mlpack.org/docs/mlpack-git/doxygen.php?doc=classmlpack_1_1gmm_1_1GMM.html MLPack(C++)]&lt;br /&gt;
# [http://arma.sourceforge.net/docs.html#gmm_diag Armadillo(C++)]&lt;br /&gt;
# [https://www.mathworks.com/help/stats/fitgmdist.html Matlab]&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;/div&gt;</summary>
		<author><name>Algoman</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%9C%D0%B0%D1%80%D0%B8%D1%8F_%D0%93%D0%BE%D1%82%D0%BC%D0%B0%D0%BD/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8,_%D0%BE%D1%81%D0%BD%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9_%D0%BD%D0%B0_%D0%BC%D0%B0%D0%BA%D1%81%D0%B8%D0%BC%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BE%D0%B6%D0%B8%D0%B4%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=15486</id>
		<title>Участник:Мария Готман/Алгоритм кластеризации, основанный на максимизации ожидания</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D0%B0%D1%80%D0%B8%D1%8F_%D0%93%D0%BE%D1%82%D0%BC%D0%B0%D0%BD/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8,_%D0%BE%D1%81%D0%BD%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9_%D0%BD%D0%B0_%D0%BC%D0%B0%D0%BA%D1%81%D0%B8%D0%BC%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BE%D0%B6%D0%B8%D0%B4%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=15486"/>
		<updated>2016-11-01T10:44:08Z</updated>

		<summary type="html">&lt;p&gt;Algoman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Algoman}}&lt;br /&gt;
&lt;br /&gt;
Авторы описания: [[Участник:Мария_Готман|Готман М.Л.]], [[Участник:Julia_lukashkina|Лукашкина Ю.Н.]]&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Задача кластеризации — это задача разбиения заданной входной выборки объектов на непересекающиеся подмножества, называемые кластерами, так, чтобы каждый кластер состоял из схожих объектов, а объекты разных кластеров существенно отличались. &lt;br /&gt;
&lt;br /&gt;
Для решения этой задачи можно использовать, например, метод максимизации ожидания, также известный как EM-алгоритм (англ. expectation-maximization) &amp;lt;ref&amp;gt;Воронцов К.В.; Математические методы обучения по прецедентам (теория обучения машин)&amp;lt;/ref&amp;gt;. В таком случае делается предположение, что входные данные — смесь многомерных нормальных распределений, соотвественно отдельный кластер — это одна компонента смеси. Предполагается, что количество кластеров является входным параметром алгоритма (существуют модификации EM-алгоритма, которые автоматически находят число кластеров, но они не рассматриваются в данной статье). Результат работы EM-алгоритма — веса кластеров и найденные параметры нормальных распределений для каждого кластера: вектора математических ожиданий и матрицы ковариации. &lt;br /&gt;
&lt;br /&gt;
Алгоритм EM кластеризации основан на итеративном выполнении двух последовательных шагов: E-шага и M-шага. На E-шаге вычисляеются вспомогательные (скрытые) переменные, которые характеризуют апостериорную вероятность того, что определенный обучающий объект получен из фиксированной компоненты смеси. На M-шаге с помощью вычесленных скрытых переменных производится обновление параметров смеси: по определённым формулам пересчитываются веса кластеров, их математические ожидания и матрицы ковариаций.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что на работу EM-алгоритма значительно влияет начальное приближение его параметров. При неудачной инициализации алгоритм может не сойтись или сойтись в локальный экстремум.&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается частный случай EM-алгоритма, который работает с двумерными входными данными.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Em clusters 4.png|400px|thumb|center|Пример работы EM-алгоритма для 5ти кластеров.]]&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассматривается смесь нормальных распределений &amp;lt;math&amp;gt;p(x)=\sum_{j=1}^kw_jp_j(x), \sum_{j=1}^kw_j =1, w_j \ge 0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм кластеризации, основанный на максимизации правдоподобия, итеративно выполняет два шага: E-шаг и M-шаг.&lt;br /&gt;
Идея алгоритма заключается в введении матрицы скрытых переменных &amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;g_{ij} \equiv P(\theta_j |x_i)&amp;lt;/math&amp;gt; обозначает вероятность принадлежности &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го объекта &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-му кластеру.&lt;br /&gt;
&lt;br /&gt;
На Е-шаге вычисляется ожидаемое значение скрытых переменных, на М-шаге выполняется максимизация логарифма полного правдоподобия, результатом которой являются новые значения параметров модели.&lt;br /&gt;
&lt;br /&gt;
На вход алгоритму подается матрица объектов-признаков &amp;lt;math&amp;gt;X \in \R^{m \times d}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; — количество кластеров.&lt;br /&gt;
&lt;br /&gt;
На выходе получаем набор параметров модели для каждого кластера &amp;lt;math&amp;gt;\Theta = (w_1,...,w_k;\;\mu_1,...,\mu_k;\;\Sigma_1,...,\Sigma_k)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;w_j&amp;lt;/math&amp;gt; — вес &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-го кластера в смеси нормальных распределений, &amp;lt;math&amp;gt;\mu_j&amp;lt;/math&amp;gt; — математическое ожидание &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-ой компоненты смеси, &amp;lt;math&amp;gt;\Sigma_j&amp;lt;/math&amp;gt; — матрица ковариации &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-ой компоненты смеси.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;E-шаг&amp;lt;/b&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;g_{ij} = \frac{w_jN(x_i;\mu_j, \Sigma_j)}{\sum_{s=1}^k w_sN(x_i;\mu_s, \Sigma_s)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;M-шаг&amp;lt;/b&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;Q(\Theta) = \ln\prod_{i=1}^mp(x_i) = \sum_{i=1}^m\ln\sum_{j=1}^kw_jp_j(x_i) \rightarrow \max_{\Theta}&amp;lt;/math&amp;gt;, при условии &amp;lt;math&amp;gt;\sum_{j=1}^kw_j=1&amp;lt;/math&amp;gt;, где&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;p_j(x_i) = N(x_i;\mu_j, \Sigma_j) = \frac1{(2\pi)^{d/2}\sqrt{|\Sigma_j|}} \exp \biggl(-\frac{1}{2}(x_i - \mu_j) \Sigma_j^{-1} (x_i - \mu_j)^T\biggr) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Решением оптимизационной задачи являются формулы для пересчета параметров:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;w_j = \frac1m\sum_{i=1}^m g_{ij}&amp;lt;/math&amp;gt;, &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\mu_j = \frac1{mw_j}\sum_{i=1}^m g_{ij}x_i&amp;lt;/math&amp;gt;, &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\Sigma_j = \frac1{mw_j}\sum_{i=1}^m g_{ij}(x_i - \mu_j)(x_i - \mu_j)^T,\; j = 1, \dots, k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро алгоритма представляет собой итерационное вычисление всех параметров модели, независимое по &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; объектам выборки &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt;.&lt;br /&gt;
На каждой итерации алгоритма на Е-шаге пересчитывается значение скрытых переменных, на M-шаге пересчет параметров модели с учетом скрытых переменных.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как записано в [[#Вычислительное ядро алгоритма|описании ядра алгоритма]], основную часть метода составляют вычисления элементов матрицы G на E шаге, и пересчет параметров &amp;lt;math&amp;gt;\Theta&amp;lt;/math&amp;gt; на M-шаге.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
# Инициализация параметров&lt;br /&gt;
# for iter = 1 : max_iterations&lt;br /&gt;
# [E-шаг]&lt;br /&gt;
## вычисление &amp;lt;math&amp;gt;\Sigma_j^{-1}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\frac1{(2\pi)^{d/2}\sqrt{|\Sigma_j|}}, j = 1 : k&amp;lt;/math&amp;gt;&lt;br /&gt;
## вычисление &amp;lt;math&amp;gt;g_{ij},\;i = 1 : m, \; j = 1 : k&amp;lt;/math&amp;gt;&lt;br /&gt;
## вычисление &amp;lt;math&amp;gt;LL_i&amp;lt;/math&amp;gt; (логарифм правдоподобия), &amp;lt;math&amp;gt;\;i = 1 : m&amp;lt;/math&amp;gt;&lt;br /&gt;
# [M-шаг]&lt;br /&gt;
## вычисление &amp;lt;math&amp;gt;\tilde w_j = \sum_{i=1}^m g_{ij}, \; j = 1 : m&amp;lt;/math&amp;gt;&lt;br /&gt;
## вычисление &amp;lt;math&amp;gt;\tilde \mu_j = \sum_{i=1}^m g_{ij}x_i,\; j = 1 : k&amp;lt;/math&amp;gt;&lt;br /&gt;
## вычисление &amp;lt;math&amp;gt;\tilde \Sigma_j = \sum_{i=1}^m g_{ij}(x_i - \mu_j)^T(x_i - \mu_j),\; j = 1 : k&amp;lt;/math&amp;gt;&lt;br /&gt;
## нормировка &amp;lt;math&amp;gt;w_j = \frac{\tilde w_j}{m}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\mu_j = \frac{\tilde \mu_j}{w_j}, \tilde \Sigma_j = \frac{\tilde \Sigma_j}{w_j}, \;j = 1 : k&amp;lt;/math&amp;gt;&lt;br /&gt;
# вычисление  изменения логарифма правдоподобия&amp;lt;math&amp;gt;\Delta LL&amp;lt;/math&amp;gt; &lt;br /&gt;
# if (&amp;lt;math&amp;gt;\Delta LL &amp;lt; \varepsilon&amp;lt;/math&amp;gt;) then break;&lt;br /&gt;
# end for&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&amp;lt;b&amp;gt;E-шаг&amp;lt;/b&amp;gt;:&lt;br /&gt;
# вычисление обратной матрицы &amp;lt;math&amp;gt;\Sigma_j^{-1}, j = 1 : k&amp;lt;/math&amp;gt; при фиксированном &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; для двумерного случая по явным формулам имеет сложность &amp;lt;math&amp;gt;O(d^2)&amp;lt;/math&amp;gt;, для всех кластеров — &amp;lt;math&amp;gt;O(d^2k)&amp;lt;/math&amp;gt;&lt;br /&gt;
# вычисление &amp;lt;math&amp;gt;g_{ij}, i = 1 : m, j = 1 : k&amp;lt;/math&amp;gt; при фиксированных &amp;lt;math&amp;gt;i, j&amp;lt;/math&amp;gt; имеет сложность &amp;lt;math&amp;gt;O(d)&amp;lt;/math&amp;gt;, сложность вычисления матрицы G — &amp;lt;math&amp;gt;O(dmk)&amp;lt;/math&amp;gt;&lt;br /&gt;
# вычисление &amp;lt;math&amp;gt;LL_i, i = 1 : m&amp;lt;/math&amp;gt; при фиксированном &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; имеет сложность &amp;lt;math&amp;gt;O(k)&amp;lt;/math&amp;gt;, для всех объектов имеет сложность &amp;lt;math&amp;gt;O(mk)&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;b&amp;gt;M-шаг&amp;lt;/b&amp;gt;:&lt;br /&gt;
# вычисление &amp;lt;math&amp;gt;w_j,  j = 1 : k&amp;lt;/math&amp;gt; при фиксированном &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; имеет сложность &amp;lt;math&amp;gt;O(m)&amp;lt;/math&amp;gt;, для весов всех кластеров — &amp;lt;math&amp;gt;O(mk)&amp;lt;/math&amp;gt;&lt;br /&gt;
# вычисление &amp;lt;math&amp;gt;\mu_j, j = 1 : k&amp;lt;/math&amp;gt; при фиксированном &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; имеет сложность &amp;lt;math&amp;gt;O(dm)&amp;lt;/math&amp;gt;, для всех кластеров — &amp;lt;math&amp;gt;O(dmk)&amp;lt;/math&amp;gt;&lt;br /&gt;
# вычисление &amp;lt;math&amp;gt;\Sigma_j, j = 1 : k&amp;lt;/math&amp;gt; при фиксированном &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; имеет сложность &amp;lt;math&amp;gt;O(d^2m)&amp;lt;/math&amp;gt;, для всех кластеров — &amp;lt;math&amp;gt;O(d^2mk)&amp;lt;/math&amp;gt;&lt;br /&gt;
# нормировка &amp;lt;math&amp;gt;w&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\mu_j = \frac{\mu_j}{w_j}, \Sigma_j = \frac{\Sigma_j}{w_j}, j = 1 : k&amp;lt;/math&amp;gt; имеет сложность &amp;lt;math&amp;gt;O(k)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;O(dk)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;O(d^2k)&amp;lt;/math&amp;gt;&lt;br /&gt;
# вычисление  изменения логарифма правдоподобия&amp;lt;math&amp;gt;\Delta LL&amp;lt;/math&amp;gt; имеет сложность &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Сложность алгоритма на одной итерации&amp;lt;/b&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O(k(d^2+dm+m+m+dm+d^2m+1+d+d^2)) = O(d^2mk)&amp;lt;/math&amp;gt;, так как мы рассматриваем задачу для двумерного случая, то есть &amp;lt;math&amp;gt;d=2&amp;lt;/math&amp;gt;, множитель &amp;lt;math&amp;gt;d^2&amp;lt;/math&amp;gt; можно отнести в константу, итоговая сложность вычисления на одной итерации &amp;lt;math&amp;gt;O(mk)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Для &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; итераций итоговая сложность алгоритма будет равна&amp;lt;/b&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O(mkn)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; — число объектов, &amp;lt;math&amp;gt;k&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;
Опишем граф алгоритма для следующих входных данных: &amp;lt;math&amp;gt;m = 3,\; k = 2,\; d = 2&amp;lt;/math&amp;gt;, то есть 3 входных объекта и 2 кластера. &lt;br /&gt;
&lt;br /&gt;
На рис.1 показана макроструктура EM-алгоритма. Входными данными в таком случае являются матрица &amp;lt;math&amp;gt;X \in \R^{3 \times 2}&amp;lt;/math&amp;gt; и число кластеров &amp;lt;math&amp;gt;k = 2&amp;lt;/math&amp;gt;. &lt;br /&gt;
На шаге &amp;lt;math&amp;gt;\mathbf{init}&amp;lt;/math&amp;gt; происходит инициализация начальных приближений параметров модели и затем итеративное повторение &amp;lt;math&amp;gt;\mathbf{E}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\mathbf{M}&amp;lt;/math&amp;gt; шагов алгоритма. &lt;br /&gt;
&lt;br /&gt;
[[file:EM.png|thumb|center|300px|Рис.1. Граф EM-алгоритма с отображением входных и выходных данных]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;E-шаг.&amp;lt;/b&amp;gt; На рис.2 детально изображена схема E-шага. &lt;br /&gt;
Входные параметры &amp;lt;math&amp;gt;x_1,\; x_2,\; x_3 \in \R^{1 \times 2}&amp;lt;/math&amp;gt; являются строчками входной матрицы &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt;, также на вход подаются текущие приближения векторов средних значений (&amp;lt;math&amp;gt;\mu_1, \;\mu_2&amp;lt;/math&amp;gt;), матриц ковариаций (&amp;lt;math&amp;gt;\Sigma_1, \Sigma_2&amp;lt;/math&amp;gt;) и весов &amp;lt;math&amp;gt;w&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Вершинами &amp;lt;math&amp;gt;\mathbf{eI}&amp;lt;/math&amp;gt; обозначена операция нахождения обратной матрицы &amp;lt;math&amp;gt;\Sigma_j^{-1},\; j = 1,2&amp;lt;/math&amp;gt;. Вершины группы &amp;lt;math&amp;gt;\mathbf{eS}&amp;lt;/math&amp;gt; обозначают вычитание векторов &amp;lt;math&amp;gt;x_i - \mu_j,\; i = 1,2,3; \; j = 1, 2&amp;lt;/math&amp;gt;. Салатовые узлы графа &amp;lt;math&amp;gt;\mathbf{eE}&amp;lt;/math&amp;gt; обозначают вычисление ненормированного значения &amp;lt;math&amp;gt;g_{ij}, \;i = 1,2,3;\;j=1,2&amp;lt;/math&amp;gt; по формулам из раздела [[#Схема реализации последовательного алгоритма|описания алгоритма]]. Далее выход вершин этой группы подаётся на вход вершинам &amp;lt;math&amp;gt;\mathbf{eN}&amp;lt;/math&amp;gt;, которые обозначают нормировку, затем в &amp;lt;math&amp;gt;\mathbf{eL}&amp;lt;/math&amp;gt; происходит подсчет логарифма правдоподобия. На выходе этого графа получаются скрытые переменные &amp;lt;math&amp;gt;g_{ij}&amp;lt;/math&amp;gt; и логарифм правдоподобия LL.&lt;br /&gt;
 &lt;br /&gt;
[[file:EM_E_step.png|thumb|center|500px|Рис.2. Граф E-шага с отображением входных и выходных данных]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;M-шаг.&amp;lt;/b&amp;gt; На рисунке 3 изображена схема M-шага.&lt;br /&gt;
Входными параметрами являются: исходные объекты &amp;lt;math&amp;gt;x_1,\; x_2,\; x_3 \in \R^{1 \times 2}&amp;lt;/math&amp;gt;, скрытые переменные &amp;lt;math&amp;gt;g_{11},\;g_{21},\;g_{31},\;\mu_1&amp;lt;/math&amp;gt; для пересчета параметров первого кластера и &amp;lt;math&amp;gt;g_{12},\;g_{22},\;g_{32},\;\mu_2&amp;lt;/math&amp;gt; — для второго.&lt;br /&gt;
&lt;br /&gt;
Вершина &amp;lt;math&amp;gt;\mathbf{m}\boldsymbol{\mu}&amp;lt;/math&amp;gt; обозначает подсчет слагаемого математического ожидания для одного объекта, затем на шаге &amp;lt;math&amp;gt;\mathbf{mS_1}&amp;lt;/math&amp;gt; происходит суммирование слагаемых, и, наконец, на шаге &amp;lt;math&amp;gt;\mathbf{mN_1}&amp;lt;/math&amp;gt; нормировка математического ожидания, выходом являются &amp;lt;math&amp;gt;\mu_1,\;\mu_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
Вершина &amp;lt;math&amp;gt;\mathbf{m}\boldsymbol{\Sigma}&amp;lt;/math&amp;gt; обозначает подсчет слагаемого матрицы ковариации для одного объекта, затем на шаге &amp;lt;math&amp;gt;\mathbf{mS_2}&amp;lt;/math&amp;gt; происходит суммирование слагаемых, и, наконец, на шаге &amp;lt;math&amp;gt;\mathbf{mN_2}&amp;lt;/math&amp;gt; нормировка матрицы ковариации, выходом являются &amp;lt;math&amp;gt;\Sigma_1,\;\Sigma_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
Операция &amp;lt;math&amp;gt;\mathbf{mS_3}&amp;lt;/math&amp;gt; обозначает вычисление ненормированного веса для одного шага, затем при выполнении &amp;lt;math&amp;gt;\mathbf{mN_3}&amp;lt;/math&amp;gt; происходит нормировка весов, выходом являются &amp;lt;math&amp;gt;w_1,\;w_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[file:EM_M_step.png|thumb|center|500px|Рис.3. Граф M-шага с отображением входных и выходных данных]]&lt;br /&gt;
&lt;br /&gt;
На рис.1 показана структура ЕM-алгоритма для кластеризации, на рис.2 — структура E-шага  и на рис.3 — структура M-шага.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Как видно из информационного графа, возможно распараллеливание как по кластерам, так и по объектам. Однако, в реальных задачах число кластеров много меньше числа объектов, поэтому распараллеливание по кластерам нецелесообразно.&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается вариант распараллеливания по объектам. Стоит отметить, что важно корректно организовать работу с параметрами модели (матрицами ковариаций, средними значениями и весами), чтобы не произошло ситуации гонки за ресурсами &amp;lt;ref&amp;gt;Воеводин В.В., Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: плотная вещественная матрица объекты-признаки &amp;lt;math&amp;gt;X \in \R^{m \times d}&amp;lt;/math&amp;gt;, количество кластеров &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;m \times d + 1&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: вектор весов &amp;lt;math&amp;gt;w \in \R^{k \times 1}&amp;lt;/math&amp;gt;,  &amp;lt;math&amp;gt;\;\;k&amp;lt;/math&amp;gt; векторов &amp;lt;math&amp;gt;\mu_j \in \R^{d \times 1}&amp;lt;/math&amp;gt;,  &amp;lt;math&amp;gt;\;\;k&amp;lt;/math&amp;gt; матриц &amp;lt;math&amp;gt;\Sigma \in \R^{d \times d}&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;k \times (d \times d + d + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Стоит заметить, что модель смеси распеределения полностью восстанавливается по выходным данным, и задача предсказания метки кластера для входных объектов является тривиальной.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]] алгоритма равна отношению числа операций к суммарному объему входных и выходных данных. Она показывает, сколько операций приходится на единицу переданных данных. Несмотря на простоту данного понятия, это значение исключительно полезно на практике: чем выше  вычислительная мощность, тем меньше накладных расходов вызывает перемещение данных для их обработки, например, на сопроцессоре, ускорителе или другом узле кластера. Например, вычислительная мощность скалярного произведения двух векторов равна всего лишь &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а вычислительная мощность алгоритма умножения двух квадратных матриц равна &amp;lt;math&amp;gt;2n/3&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
EM-алгоритм не является устойчивым, результат его работы сильно зависит от начальных приближений параметров. При неудачном выборе начальных приближений алгоритм может не сойтись или сойтись  в локальный экстремум. &lt;br /&gt;
&lt;br /&gt;
Также, алгоритм не является детерминированным. Так как в начале работы алгоритма происходит инициализация начальных параметров случайным образом (с учетом положительной определенности и симметричности матрицы ковариации), он не может быть детерминирован.&lt;br /&gt;
&lt;br /&gt;
Алгоритм сбалансирован по E и M шагам, затраты на выполнение этих этапов примерно одинаковы.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
В данном разделе приведем код реализации последовательного алгоритма.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot;&amp;gt;&lt;br /&gt;
double_vector em_algo::expectation_step(double_matrix&amp;amp; features)&lt;br /&gt;
{&lt;br /&gt;
    long n_objects = features.size1();&lt;br /&gt;
    int n_clusters = parameters.sigmas.size();&lt;br /&gt;
    double pi = boost::math::constants::pi&amp;lt;double&amp;gt;();&lt;br /&gt;
&lt;br /&gt;
    // precalculate inverse matrices and dets&lt;br /&gt;
    std::vector&amp;lt;double_matrix&amp;gt; sigmas_inverted(n_clusters);&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt; norm_distribution_denominator(n_clusters);&lt;br /&gt;
    for (int i = 0; i &amp;lt; n_clusters; ++i)&lt;br /&gt;
    {        &lt;br /&gt;
        double_matrix sigma_inverted(parameters.sigmas[i].size1(), parameters.sigmas[i].size2());&lt;br /&gt;
        double det = InvertMatrix(parameters.sigmas[i], sigma_inverted);&lt;br /&gt;
        if (det == 0)&lt;br /&gt;
        {&lt;br /&gt;
            std::cerr &amp;lt;&amp;lt; &amp;quot;Matrix can not be inverted\n&amp;quot;;&lt;br /&gt;
            exit(1);&lt;br /&gt;
        }&lt;br /&gt;
        norm_distribution_denominator[i] = sqrt(pow(2 * pi, parameters.n_features) * det);&lt;br /&gt;
        sigmas_inverted[i] = sigma_inverted;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    hidden_vars = double_matrix(n_objects, n_clusters);&lt;br /&gt;
    double_vector log_likelihood(n_objects, 0);&lt;br /&gt;
&lt;br /&gt;
    for (auto i = 0; i &amp;lt; n_objects; ++i)&lt;br /&gt;
    {&lt;br /&gt;
        double_matrix_row x(features, i);&lt;br /&gt;
        double norm_value = 0;&lt;br /&gt;
        for (auto j = 0; j &amp;lt; n_clusters; ++j)&lt;br /&gt;
        {&lt;br /&gt;
            double_matrix_column current_means(parameters.means, j);&lt;br /&gt;
            double_vector x_centered = x - current_means;&lt;br /&gt;
&lt;br /&gt;
            double exp_power = -0.5 * inner_prod(prod(x_centered, sigmas_inverted[j]), x_centered);&lt;br /&gt;
            hidden_vars(i, j) = parameters.weights(j) * exp(exp_power) / norm_distribution_denominator[j];&lt;br /&gt;
&lt;br /&gt;
            norm_value += hidden_vars(i, j);&lt;br /&gt;
        }&lt;br /&gt;
        double_matrix_row hidden_vars_row(hidden_vars, i);&lt;br /&gt;
        if (norm_value != 0)&lt;br /&gt;
        {&lt;br /&gt;
            hidden_vars_row = hidden_vars_row / norm_value;&lt;br /&gt;
            log_likelihood(i) = log(inner_prod(hidden_vars_row, parameters.weights));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    return log_likelihood;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void em_algo::maximization_step(double_matrix&amp;amp; features)&lt;br /&gt;
{&lt;br /&gt;
    int n_objects = features.size1();&lt;br /&gt;
&lt;br /&gt;
    double_vector w = double_vector(n_clusters, 0.0);&lt;br /&gt;
    double_matrix means = double_matrix(parameters.n_features, n_clusters, 0.0);&lt;br /&gt;
    std::vector&amp;lt;double_matrix&amp;gt; sigmas;&lt;br /&gt;
    for (int j = 0; j &amp;lt; n_clusters; ++j)&lt;br /&gt;
        sigmas.push_back(double_matrix(parameters.n_features, parameters.n_features, 0.0));&lt;br /&gt;
&lt;br /&gt;
    for (int i = 0; i &amp;lt; n_objects; ++i)&lt;br /&gt;
    {&lt;br /&gt;
        double_matrix_row x_i = row(features, i);&lt;br /&gt;
&lt;br /&gt;
        for (int j = 0; j &amp;lt; n_clusters; ++j)&lt;br /&gt;
        {&lt;br /&gt;
            double g = hidden_vars(i, j);&lt;br /&gt;
            w(j) += g;&lt;br /&gt;
&lt;br /&gt;
            double_matrix_column single_mean = column(means, j);&lt;br /&gt;
&lt;br /&gt;
            single_mean += g * x_i;&lt;br /&gt;
&lt;br /&gt;
            double_vector x_centered = x_i - column(parameters.means, j);&lt;br /&gt;
            for (int k = 0; k &amp;lt; parameters.n_features; ++k)&lt;br /&gt;
                for (int l = 0; l &amp;lt; parameters.n_features; ++l)&lt;br /&gt;
                    sigmas[j](k, l) = sigmas[j](k, l) + g * x_centered(k) * x_centered(l);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    // update weights&lt;br /&gt;
    parameters.weights = w / n_objects;&lt;br /&gt;
&lt;br /&gt;
    for (int j = 0; j &amp;lt; n_clusters; ++j) {&lt;br /&gt;
        double weight = w(j);&lt;br /&gt;
        // update means&lt;br /&gt;
        double_matrix_column means_old = column(parameters.means, j);&lt;br /&gt;
        double_matrix_column means_new = column(means, j);&lt;br /&gt;
        means_old = means_new / weight;&lt;br /&gt;
&lt;br /&gt;
        // update sigmas&lt;br /&gt;
        parameters.sigmas[j] = sigmas[j] / weight;&lt;br /&gt;
        for (int k = 0; k &amp;lt; parameters.n_features; ++k)&lt;br /&gt;
            parameters.sigmas[j](k, k) = parameters.sigmas[j](k, k) + tol;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
bool em_algo::is_likelihood_stabilized(double_vector likelihood, double_vector previous_likelihood)&lt;br /&gt;
{&lt;br /&gt;
    double likelihood_diff = sum(likelihood) - sum(previous_likelihood);&lt;br /&gt;
    return fabs(likelihood_diff) &amp;lt; tol;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
model em_algo::process(double_matrix&amp;amp; features, int max_iterations)&lt;br /&gt;
{&lt;br /&gt;
    int iteration = 0;&lt;br /&gt;
    double_vector likelihood, previous_likelihood;&lt;br /&gt;
    while (iteration++ &amp;lt; max_iterations &amp;amp;&amp;amp; (iteration &amp;lt;= 2 || !is_likelihood_stabilized(likelihood, previous_likelihood)))&lt;br /&gt;
    {&lt;br /&gt;
        previous_likelihood = likelihood;&lt;br /&gt;
        likelihood = expectation_step(features);&lt;br /&gt;
        maximization_step(features);&lt;br /&gt;
    }&lt;br /&gt;
    return parameters;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Возможной реализацией является перестановка местами циклов по объектам и по кластерам на E и М шаге. В данном случае внешний цикл проходит по объектам, так как подразумевается дальнейшая реализации распараллеливания по объектам. При реализации только последовательного алгоритма более понятной версией будет реализация внешнего цикла по кластерам, и внутреннего по объектам, но такая реализация увеличит число обращений в память и общее время работы алгоритма.&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;k = 4 &amp;lt;/math&amp;gt;, и, также, было зафиксировано ядро рандомизации, чтобы избавиться от случайности различного выбора начального приближения параметров. Для показательности результатов условие дострочного завершения работы алгоритма в случае стабилизирования логарифма правдоподобия игнорировалось, и для каждого запуска проводилось 50 итераций EM-алгоритма.&lt;br /&gt;
&lt;br /&gt;
Для экспериментов было сгенерировано 20 выборок разного размера: от 40000 объектов до 200000 с шагом в 10000. Для каждой выборки время работы алгоритма усреднялось по нескольким запускам, чтобы избежать выбросов.&lt;br /&gt;
&lt;br /&gt;
Для работы с многопоточностью использовалась библиотека OpenMP. С помощью нее были распараллелены основные циклы по объектам на E и M шаге.&lt;br /&gt;
&lt;br /&gt;
Эксперименты проводились на компьютере с процессором Intel(R) Core(TM) i7-5820K @ 3.30GHz, который поддерживает до 12ти потоков.&lt;br /&gt;
&lt;br /&gt;
Как видно на рис. 4, производительность растет до 12 процессов, после чего время работы алгоритма снова начинает увеличиваться, то есть использование более 12 процессов при рассматриваемой конфигурации процессора не имеет смысла. Заметим также, что в увеличением числа точек, скорость работы программы линейно увеличивается.&lt;br /&gt;
&lt;br /&gt;
[[file:EM performance.png|thumb|center|700px|Рис. 4 Время работы EM алгоритма в зависимости от числа процессов и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
В результате проведённых экспериментов был получен следующий диапазон эффективности реализации алгоритма:&lt;br /&gt;
&lt;br /&gt;
*	минимальная эффективность реализации 0,00072%;&lt;br /&gt;
*	максимальная эффективность реализации 25.5037%.&lt;br /&gt;
&lt;br /&gt;
[[file:EM_Efficiency.png|thumb|center|700px|Рис. 4 Эффективность EM алгоритма в зависимости от числа процессов и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Существуют следующие последовательные реализации EM-алгоритма для кластеризации: [http://docs.opencv.org/2.4/modules/ml/doc/expectation_maximization.html# opencv], [http://scikit-learn.org/stable/modules/mixture.html scikit-learn]. &lt;br /&gt;
&lt;br /&gt;
Также существует несколько параллельных реализаций, описанных в следующих статьях:&lt;br /&gt;
&lt;br /&gt;
В статье &amp;lt;ref&amp;gt;López-de-Teruel P. E., García J. M., Acacio; The Parallel EM Algorithm and its Applications in Computer Vision&amp;lt;/ref&amp;gt;  авторы предлагают распределить вычисление скрытых переменных для каждого объекта между процессорами и на каждой итерации производить нормализацию. M-шаг предлагается параллелить по компонентам, что требует реализации корректного взаимодействия между процессорами. Предложенный вариант распараллеливания был реализован и протестирован авторами статьи с помощью MPI библиотеки MPICH. &lt;br /&gt;
&lt;br /&gt;
Авторы статьи &amp;lt;ref&amp;gt;Abhinandan Das, Mayur Datar, Ashutosh Garg; Google News Personalization: Scalable Online Collaborative Filtering&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&amp;lt;/ref&amp;gt; используют MapReduce для распараллеливания EM-алгоритма для PLSI моделей.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;/div&gt;</summary>
		<author><name>Algoman</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%95%D0%BA%D0%B0%D1%82%D0%B5%D1%80%D0%B8%D0%BD%D0%B0%D0%9A%D0%BE%D0%B7%D1%8B%D1%80%D0%B5%D0%B2%D0%B0/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%B4%D0%B8%D0%BD%D0%B0%D0%BC%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B9_%D0%B8%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B9_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_CHAMELEON&amp;diff=15485</id>
		<title>Участник:ЕкатеринаКозырева/Алгоритм динамической иерархической кластеризации CHAMELEON</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%95%D0%BA%D0%B0%D1%82%D0%B5%D1%80%D0%B8%D0%BD%D0%B0%D0%9A%D0%BE%D0%B7%D1%8B%D1%80%D0%B5%D0%B2%D0%B0/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%B4%D0%B8%D0%BD%D0%B0%D0%BC%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B9_%D0%B8%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B9_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_CHAMELEON&amp;diff=15485"/>
		<updated>2016-11-01T10:43:27Z</updated>

		<summary type="html">&lt;p&gt;Algoman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Algoman}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Алгоритм динамической иерархической кластеризации CHAMELEON&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(nm + n log n + m^2 log m)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;\frac{n (n - 1)}{2}&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(n+ n log(n) + m^2 log (m) + m log(m))&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;
}}&lt;br /&gt;
&lt;br /&gt;
Автор описания [[Участник:ЕкатеринаКозырева|Е.А.Козырева]]&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Алгоритм CHAMELEON был предложен в 1999 году тремя учеными из университета Миннесоты – George Karypis, Eui-Hong (Sam) Han и Vipin Kumar&amp;lt;ref&amp;gt;George Karypis, Eui-Hong (Sam) Han и Vipin Kumar, «Chameleon: Hierarchical Clustering Using Dynamic Modeling», 1999.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Предназначен для решения задач кластеризации. Кластеризация (или кластерный анализ) — это задача разбиения множества объектов на группы, называемые кластерами. Внутри каждой группы должны оказаться «похожие» объекты, а объекты разных группы должны быть как можно более отличны.&lt;br /&gt;
&lt;br /&gt;
CHAMELEON - это агломеративный иерархический алгоритм кластеризации, ключевой особенностью которого является то, что он учитывает и взаимную связность, и сходство при определении наиболее похожей пары подкластеров, основываясь на динамической модели. Это означает, что в процессе кластеризации два кластера объединяются, только если их относительная взаимная связность и относительное взаимное сходство являются высокими по отношению к внутренней взаимосвязанности кластеров и близости элементов внутри кластеров. Кроме того, CHAMELEON использует подход для моделирования степени взаимосвязанности и близости между каждой парой кластеров, который учитывает внутренние характеристики самих кластеров. Таким образом, он может автоматически адаптироваться к внутренним характеристикам объединяемых кластеров.&lt;br /&gt;
&lt;br /&gt;
CHAMELEON находит кластеры в наборе данных с помощью трехфазного алгоритма. На первой фазе происходит построение графа, путём добавления рёбер по принципу k ближайших соседей. На второй фазе CHAMELEON группирует полученные элементы в множество относительно небольших подграфов. Во время третьей фазы применяется агломеративный иерархический алгоритм кластеризации, с помощью которого находятся естесственные кластеры путем многократного объединения подграфов, полученных на прошлом этапе.&lt;br /&gt;
&lt;br /&gt;
[[File:Chameleon.png|1000px|thumb|center|Рисунок 1. Общая структура алгоритма CHAMELEON]]&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Исходные данные&#039;&#039;: &lt;br /&gt;
&lt;br /&gt;
* Множество из n точек &amp;lt;math&amp;gt;V= {v_{ij}}&amp;lt;/math&amp;gt; в метрическом пространстве, которое задано симметрической матрицей расстояний &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; размера &amp;lt;math&amp;gt;n\times n&amp;lt;/math&amp;gt;.&lt;br /&gt;
* &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество ближайших соседей для вершин, &amp;lt;math&amp;gt;k \in N, k \leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
* &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; - наименьшее число вершин, которое может содержать наибольший подграф на 2-м этапе, &amp;lt;math&amp;gt;l \in N, l \leq n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Обозначения&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; - граф, полученный путём соединения каждой точки с её &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайшими соседями.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;K= \{K_{i}\}&amp;lt;/math&amp;gt; - разбиение множества &amp;lt;math&amp;gt;V&amp;lt;/math&amp;gt; на набор попарно непересекающихся связных подмножеств, полученное в результате выполнения второй фазы алгоритма.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;G_{2} = (K, E_{2})&amp;lt;/math&amp;gt; - взвешенный граф, вершинами которого являются получившиеся подграфы, а ребрами - количество ребер исходного графа, соединяющих соответствующие подграфы.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;C = \{C_{i}\}&amp;lt;/math&amp;gt; - итоговое разбиение множества вершин графа &amp;lt;math&amp;gt;G_{2}&amp;lt;/math&amp;gt; на набор кластеров.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Вспомогательные понятия&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; - абсолютная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Определяется как сумма весов ребер, соединяющих вершины, принадлежащие &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; c вершинами из &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt;. Внутренняя связность &amp;lt;math&amp;gt;EC_{(C_{i},C_{i})}&amp;lt;/math&amp;gt; вычисляется как сумма ребер, входящих в разделитель, разбивающий &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; на два равных подграфа.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} = \frac{|EC_{(C_{i},C_{j})}|}{(|EC_{C_{i}}|+|EC_{C_{j}}|)/2}&amp;lt;/math&amp;gt; - относительная взаимная связность пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt; - абсолютное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Подсчитывается как среднее сходство между соединенными вершинами, принадлежащими &amp;lt;math&amp;gt;C{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C{j}&amp;lt;/math&amp;gt; соответственно. Соединения обусловлены разбиением общего графа, полученного на первом этапе алгоритма.&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}= \frac{S_{EC_{(C_{i},C_{j})}}}{\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{i})}}+\frac{|C_{i}|}{|C_{i}+C_{j}|}*S_{EC_{(C_{j})}}}&amp;lt;/math&amp;gt; - относительное взаимное сходство пары кластеров &amp;lt;math&amp;gt;C_{i}, C{j}&amp;lt;/math&amp;gt;. Определяется как абсолютное сходство между этой парой кластеров, нормализованное с учетом их внутреннего сходства&amp;lt;ref&amp;gt;http://studopedia.ru/7_41934_algoritm-dinamicheskoy-ierarhicheskoy-klasterizatsii-CHAMELEON.html&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый этап&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
На первом этапе, согласно графо-ориентированному подходу, происходит построение графа &amp;lt;math&amp;gt;G = (V, E)&amp;lt;/math&amp;gt; на матрице сходства объектов по принципу k ближайших соседей. Две вершины такого графа соединяет ребро, если объект, соответствующий любой из этих вершин попадает в число k наиболее близких объектов для объекта, соответствующего другой вершине из данной пары.&lt;br /&gt;
[[Файл:Снимок chameleon 2.png|2000px|thumb|Рисунок 2. Объекты в пространстве - слева, граф по принципу 1-го ближайшего соседа - по центру, граф по принципу 3-х ближайших соседей - справа ]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй этап&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Алгоритм разделяет полученный граф на множество сравнительно малых подграфов &amp;lt;math&amp;gt;K= \{K_{i}\}&amp;lt;/math&amp;gt;. Разделение происходит последовательно. На каждом шаге выбирается подграф, содержащий наибольшее число вершин. Этот граф разделяется на два подграфа так, что разделитель ребер графа минимален и каждый из получаемых подграфов содержит не менее 25 % вершин исходного графа. Процесс разделения останавливается, когда наибольший подграф содержит меньше некоторого заданного числа вершин. Обычно величина этого параметра задается равной значению от 1 до 5 % от числа объектов. Полученное множество связных графов считается множеством начальных кластеров, на котором требуется провести последовательное иерархическое объединение.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Третий этап&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Третий этап заключается в итеративном преобразовании множества подграфов &amp;lt;math&amp;gt;K= \{K_{i}\}&amp;lt;/math&amp;gt; в множество кластеров &amp;lt;math&amp;gt;C = \{C_{i}\}&amp;lt;/math&amp;gt;. Алгоритм осуществляет агломеративную иерархическую кластеризацию на основании показателей &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Существует две стратегии анализа показателей сходства. Первая подразумевает наличие некоторых пороговых значений &amp;lt;math&amp;gt;T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;T_{RC}&amp;lt;/math&amp;gt;. В соответствии с этой стратегией, алгоритм для каждого кластера &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; проверяет, отвечают ли смежные (наиболее близкие) ему кластеры условиям:&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} \geqslant T_{RI}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*&amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} \geqslant T_{RC}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если более одного смежного кластера отвечает этим условиям, то алгоритм выбирает для объединения наиболее связный кластер (граф), то есть такой кластер &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;, с которым у кластера &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; получается наибольшая абсолютная взаимная связность. По завершению прохода по всем кластерам, созданные таким образом пары объединяются. Параметры &amp;lt;math&amp;gt;T_{RI}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;T_{RC}&amp;lt;/math&amp;gt; могут использоваться для изменения характеристик получаемых кластеров.&lt;br /&gt;
&lt;br /&gt;
Вторая стратегия заключается в использовании специальной функции, объединяющей понятия относительной взаимной связности и относительного взаимного сходства. На каждом шаге выбираются те кластеры для объединения, которые максимизируют эту функцию:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}*RC_{(C_{i},C_{j})}^\alpha&amp;lt;/math&amp;gt;,&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;\alpha&amp;lt;/math&amp;gt; выбирается пользователем. Если &amp;lt;math&amp;gt;\alpha &amp;gt; 1 &amp;lt;/math&amp;gt;, то алгоритм придает большее значение относительному взаимному сходству, а если &amp;lt;math&amp;gt;\alpha &amp;lt;  1 &amp;lt;/math&amp;gt;, то большее значение имеет относительная взаимная связность.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Вычисляемые данные&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;U = (u_1, u_2, ..., u_n)&amp;lt;/math&amp;gt; - n-мерный вектор, где &amp;lt;math&amp;gt;u_i \in N_{[C]}&amp;lt;/math&amp;gt; - порядковый номер кластера, к которому принадлежит вершина i исходного множества V.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм имеет три вычислительных ядра, по одному на каждый этап.&lt;br /&gt;
&lt;br /&gt;
На первом этапе вычислительным ядром является процесс нахождения &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей для каждой вершины, который заключается в анализе матрицы расстояний.&lt;br /&gt;
&lt;br /&gt;
На втором этапе вычислительным ядром является процесс поиска подходящего разбиения очередного подграфа на два графа с минимизацией разделителя ребер графа.&lt;br /&gt;
&lt;br /&gt;
На третьем этапе вычислительным ядром является расчет величин &amp;lt;math&amp;gt;EC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;S_{EC_{(C_{i},C_{j})}}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} &amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; для каждой пары смежных кластеров.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Как уже рассказывалось ранее, алгоритм включает в себя три основных этапа, каждый из которых, по сути, является отдельным алгоритмом. Этапы выполняются последовательно относительно друг друга. &lt;br /&gt;
&lt;br /&gt;
Макрооперация на первом этапе - процедура нахождения &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; ближайших соседей, на втором - процедура разбиения наибольшего подграфа на два графа, на третьем - процедура вычисления показателей сходства, на основе которых принимается решение о слиянии подграфов в кластер.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Первый этап&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;cpp&amp;quot;&amp;gt;&lt;br /&gt;
 int n; //количество вершин&lt;br /&gt;
 int k; //количество соседей&lt;br /&gt;
 int A[n][n] //матрица расстояний&lt;br /&gt;
 int D[k] //массив вершин-соседей&lt;br /&gt;
 int E[n][n] //матрица ребер графа &amp;lt;math&amp;gt;G_{2} = (K, E_{2})&amp;lt;/math&amp;gt;&lt;br /&gt;
 for i=1 to n-1 do&lt;br /&gt;
     {&lt;br /&gt;
       for j=i+1 to n do &lt;br /&gt;
            {&lt;br /&gt;
               //заполняем массив вершин-соседей вставляя новые вершины, если они ближе, чем самая далекая из массива. &lt;br /&gt;
            }&lt;br /&gt;
       for j=0 to k do &lt;br /&gt;
            {&lt;br /&gt;
               //для каждой вершины соседа заполняем соответствующую ячейку из матрицы E[n][n] единицей&lt;br /&gt;
            }&lt;br /&gt;
   &lt;br /&gt;
     }&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Второй этап&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 1. Все связные подграфы в отсортированном порядке помещаются в список;&lt;br /&gt;
 2. Берем наибольший элемент списка, вычисляем количество его вершин. Если число вершин &amp;gt; l, то идем в пункт 3. Иначе в пункт 5;&lt;br /&gt;
 3. Разбиваем подграф на два подграфа таким образом, чтобы разделитель ребер графа был минимален и каждый из получаемых подграфов содержал не менее 25 % вершин исходного графа;&lt;br /&gt;
 4. Добавляем полученные элементы в список подграфов таким образом, чтобы список оставался отсортированным. Идем в пункт 2;&lt;br /&gt;
 5. Нашли искомое множество подграфов math&amp;gt;K = \{K_{i}\}&amp;lt;/math&amp;gt;;&lt;br /&gt;
 6. Создаем и заполняем матрицу матрицу расстояний для графа &amp;lt;math&amp;gt;G_{2} = (K, E_{2})&amp;lt;/math&amp;gt;. Получаем искомый набор рёбер &amp;lt;math&amp;gt;E_{2}&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;
 1. Заводим два массива: а) массив кластеров C, полученных на предыдущем этапе, б) массив объединений кластеров F, которые мы будем получать на этом этапе;&lt;br /&gt;
 2. Берем следующий кластер &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; (на первом шаге - первый). Если все кластеры просмотрены, идем в пункт 6;&lt;br /&gt;
 3. Берем следующий кластер &amp;lt;math&amp;gt;C_{j}, i&amp;lt;&amp;gt;j&amp;lt;/math&amp;gt;. Если все кластеры просмотрены, то идем в пункт 2;&lt;br /&gt;
 4. Проверяем смежность &amp;lt;math&amp;gt;C_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_{j}&amp;lt;/math&amp;gt;. Если не смежны, то возвращаемся в пункт 3. Если смежны, идем в пункт 5;&lt;br /&gt;
 5. Рассчитываем показатели &amp;lt;math&amp;gt;RI_{(C_{i},C_{j})}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt; RC_{(C_{i},C_{j})}&amp;lt;/math&amp;gt;. Проверяем, удовлетворяют ли найденные значения условиям:&lt;br /&gt;
 *&amp;lt;math&amp;gt;RI_{(C_{i},C_{j})} \geqslant T_{RI}&amp;lt;/math&amp;gt;&lt;br /&gt;
 *&amp;lt;math&amp;gt;RC_{(C_{i},C_{j})} \geqslant T_{RC}&amp;lt;/math&amp;gt;&lt;br /&gt;
 Если нет, то идем в пункт 3. Иначе если смежность пары кластеров выше, чем у предыдущих найденных, то &amp;lt;math&amp;gt;F_{i}=j&amp;lt;/math&amp;gt;. Идем в пункт 3;&lt;br /&gt;
 6. Если в списке F есть хотя бы одна пара кластеров для слияния, то выполняем слияние, обновляем массив кластеров и массив объединений кластеров. Идем в пункт 2.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
1) Для построения графа на основе метода k ближайших соседей для n вершин требуется &amp;lt;math&amp;gt;O(n log(n))&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;J.H. Friedman, J.L. Bentley, and R.A. Finkel. An algorithm for ﬁnding best matches in logarithmic expected time. ACM Transactions on Mathematical Software, 3:209–226, 1977.&amp;lt;/ref&amp;gt;; для наборов данных большой размерности эта величина составляет &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; операций &amp;lt;ref&amp;gt;S. Berchtold, C. Bohm, D. Keim, and H.-P. Kriegel. Cost model for nearest neighbor search in high dimensional data space. In Proc. of Symposium on Principles of Database Systems, Tucson, Arizona, 1997.&amp;lt;/ref&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
2) Для выделения множества сравнительно малых связных подграфов требуется &amp;lt;math&amp;gt;nm&amp;lt;/math&amp;gt; операций, где &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - количество подграфов, полученных на втором этапе алгоритма;&lt;br /&gt;
&lt;br /&gt;
3) Формирование набора кластеров, на основе множества подграфов, полученных на предыдущем этапе, требует &amp;lt;math&amp;gt;m^2log(m)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
Итого, для n вершин получаем последовательную сложность &amp;lt;math&amp;gt;O(n log(n)+nm+m^2log(m))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
[[File:СК.png]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Первый этап работы алгоритма можно распределить между &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; процессами. На вход каждому процессу подается своя вершина, далее происходит процедура поиска &amp;lt;math&amp;gt;k&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;
&lt;br /&gt;
Второй этап распараллеливается путем подачи на вход свободному процессу очередного подграфа для разделения. Число итераций оценивается в &amp;lt;math&amp;gt;O(n log(n))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Третий этап делится на расчет показателей схожести и соединение подграфов в кластеры. Процесс расчета показателей можно распараллелить, подавая каждому процессу на вход пару подграфов. Сложность этого процесса оценивается как &amp;lt;math&amp;gt;m log(m)&amp;lt;/math&amp;gt;. Соединение подграфов в кластеры выполняется последовательно, сложность процесса составляет &amp;lt;math&amp;gt;m^2 log(m)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Таким образом получаем общую параллельную сложность алгоритма: &amp;lt;math&amp;gt;O(n+ n log(n) + m^2 log (m) + m log(m))&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;
1. Симметрическая матрица &amp;lt;math&amp;gt;A&amp;lt;/math&amp;gt; расстояний между элементами данных размера &amp;lt;math&amp;gt;n\times n&amp;lt;/math&amp;gt; с нулями на главной диагонали  (&amp;lt;math&amp;gt;a_{ii}= 0, i = 1, \ldots, N&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
2. &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество ближайших соседей для вершин (рекомендуемое значение &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; от 5 до 20 в зависимости от количества анализируемых объектов).&lt;br /&gt;
&lt;br /&gt;
3. &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; - наименьшее число вершин, которое может содержать наибольший подкластер на 2-м этапе . Величина этого параметра варьируется от 1 до 5 % от общего числа объектов.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\frac{n (n - 1)}{2}&amp;lt;/math&amp;gt; (в силу симметричности и нулевой главной диагонали достаточно хранить только  над/поддиагональные элементы).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Вектор из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; чисел &amp;lt;math&amp;gt;u_{1}, u_{2}, \ldots, u_{N}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;u_{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;Объём выходных данных&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&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; для больших наборов данных и логарифмическим для n вершин. На втором этапе сложно оценить это соотношение - оно сильно зависит от параметров &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt;. На третьем этапе соотношение равно &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Оценка &#039;&#039;вычислительной мощности&#039;&#039; выглядит следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;                  для 1-го этапа;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O(\frac{nm}{n^2+m^2})&amp;lt;/math&amp;gt;   для 2-го этапа;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O(\frac{m^2log(m)}{m^2+n})&amp;lt;/math&amp;gt; для 3-го этапа;&lt;br /&gt;
&lt;br /&gt;
Алгоритм является &#039;&#039;недетерминированным&#039;&#039;. Хотя 1-й этап детерминирован, на 2-ом этапе могут быть найдены различные разбиения на подграфы, что повлияет и на итоговый результат работы алгоритма.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
см. позднее&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Последовательная реализация алгоритма доступна по ссылке &amp;lt;ref&amp;gt;http://www.codeforge.com/article/192925&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
CHAMELEON можно реализовать с использованием графовых библиотек METIS &amp;lt;ref&amp;gt;http://glaros.dtc.umn.edu/gkhome/metis/metis/overview&lt;br /&gt;
&amp;lt;/ref&amp;gt;, hMETIS &amp;lt;ref&amp;gt;http://glaros.dtc.umn.edu/gkhome/metis/hmetis/overview&amp;lt;/ref&amp;gt; и RANN &amp;lt;ref&amp;gt;https://cran.r-project.org/web/packages/RANN/index.html&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Существует исследование, связанное с реализацией CHAMELEON посредством технологии OpenMP, с которым можно ознакомиться здесь &amp;lt;ref&amp;gt;http://research.ijcaonline.org/volume79/number8/pxc3891600.pdf&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Параллельных реализаций алгоритма CHAMELEON не найдено.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Algoman</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%D1%86%D0%B0:%D0%90%D0%BB%D0%B5%D0%BA%D1%81%D0%B0%D0%BD%D0%B4%D1%80%D0%B0/%D0%9C%D0%B5%D1%82%D0%BE%D0%B4_%D0%B2%D1%81%D1%82%D1%80%D0%B5%D1%87%D0%B8_%D0%BF%D0%BE%D1%81%D0%B5%D1%80%D0%B5%D0%B4%D0%B8%D0%BD%D0%B5&amp;diff=15112</id>
		<title>Участница:Александра/Метод встречи посередине</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D1%86%D0%B0:%D0%90%D0%BB%D0%B5%D0%BA%D1%81%D0%B0%D0%BD%D0%B4%D1%80%D0%B0/%D0%9C%D0%B5%D1%82%D0%BE%D0%B4_%D0%B2%D1%81%D1%82%D1%80%D0%B5%D1%87%D0%B8_%D0%BF%D0%BE%D1%81%D0%B5%D1%80%D0%B5%D0%B4%D0%B8%D0%BD%D0%B5&amp;diff=15112"/>
		<updated>2016-10-31T14:10:43Z</updated>

		<summary type="html">&lt;p&gt;Algoman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Algoman}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Метод встречи посередине&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(\sqrt n\log(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;O(n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &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;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
Метод &amp;quot;Встреча посередине&amp;quot; криптоанализа блочных шифров был впервые предложен в 1977 году Уитфилдом Диффи и Мартином Хеллманом &amp;lt;ref&amp;gt;(June 1977) «Exhaustive Cryptanalysis of the NBS Data Encryption Standard». Computer 10 (6): 74–84. DOI:10.1109/C-M.1977.217750&amp;lt;/ref&amp;gt;. Встреча посередине используется для ускорения перебора ключей шифра за счёт увеличения требуемой памяти. Метод применим в случае каскадного построения сложного шифра из нескольких простых, другими словами, в случае последовательного применения шифрующих преобразований на разных ключах к блокам открытого текста.&lt;br /&gt;
&lt;br /&gt;
В качестве примера шифра, поддающегося атаке &amp;quot;встреча посередине&amp;quot; можно привести криптоалгоритм 2DES, являющийся модификацией шифра DES. В 2DES открытый текст шифруется дважды алгоритмом DES на двух разных 56-битных ключах. Однако из-за атаки &amp;quot;встреча посередине&amp;quot; сложность перебора двойного ключа (112 бит) шифра 2DES составляет &amp;lt;math&amp;gt;2^{57}&amp;lt;/math&amp;gt; вместо ожидаемых &amp;lt;math&amp;gt;2^{112}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Исходные данные:&#039;&#039;&#039; открытый текст &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;, шифртекст &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Алгоритм зашифрования — композиция двух преобразований &amp;lt;math&amp;gt;T_1(x,k_1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;T_2(x,k_2)&amp;lt;/math&amp;gt;, т.е. &amp;lt;math&amp;gt;y=T_2(T_1(x,k_1),k_2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм расшифрования — &amp;lt;math&amp;gt;y=T_1^{-1}(T_2^{-1}(x,k_2),k_1)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вычисляемые данные:&#039;&#039;&#039; ключи шифрования &amp;lt;math&amp;gt;k_1 \in K_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;k_2 \in K_2&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;K_1, K_2&amp;lt;/math&amp;gt; — множества возможных ключей.&lt;br /&gt;
&lt;br /&gt;
Трудоёмкость полного перебора всех возможных пар &amp;lt;math&amp;gt;k_1,k_2&amp;lt;/math&amp;gt; составляет в среднем &amp;lt;math&amp;gt;\frac{|K_1||K_2|}{2}&amp;lt;/math&amp;gt;, а в худшем случае &amp;lt;math&amp;gt;|K_1||K_2|&amp;lt;/math&amp;gt;. Однако используя дополнительную память, можно сократить перебор.&lt;br /&gt;
&lt;br /&gt;
Предположим, что открытый текст &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; и шифртекст &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; однозначно определяют ключи &amp;lt;math&amp;gt;k_1,k_2&amp;lt;/math&amp;gt;. Составим две таблицы:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
z_1 &amp;amp; =T_1(x,k_1^1) &amp;amp; z_1^&#039; &amp;amp;=T_2^{-1}(x,k_2^1)\\\\&lt;br /&gt;
z_2 &amp;amp; =T_1(x,k_1^2) &amp;amp; z_2^&#039; &amp;amp; =T_2^{-1}(x,k_2^2)\\&lt;br /&gt;
... &amp;amp; .................  &amp;amp; ... &amp;amp; .................... \\&lt;br /&gt;
z_{|K_1|} &amp;amp; =T_1(x,k_1^{|K_1|}) &amp;amp; z_{|K_1|}^&#039; &amp;amp; =T_2^{-1}(x,k_2^{|K_1|})&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для всех &amp;lt;math&amp;gt;k_1^i \in K_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;k_2^j \in K_2&amp;lt;/math&amp;gt;. Далее таблицы объединяются и сортируются по значениям &amp;lt;math&amp;gt;z_i,z_j^&#039;&amp;lt;/math&amp;gt;. Индексы &amp;lt;math&amp;gt;i,j&amp;lt;/math&amp;gt;, при которых &amp;lt;math&amp;gt;z_i=z_j^&#039;&amp;lt;/math&amp;gt;, однозначно определяют искомую пару ключей &amp;lt;math&amp;gt;k_1=k_1^i,k_2=k_2^j&amp;lt;/math&amp;gt;. Для нахождения такой пары достаточно просмотреть отсортированную таблицу один раз.&lt;br /&gt;
&lt;br /&gt;
Если же пара открытый текст/шифртекст определяет ключ не единственном образом, то выходом алгоритма будет некоторое множество пар &amp;lt;math&amp;gt;k_1,k_2&amp;lt;/math&amp;gt;, одна из которых является истинным ключом. Для выбора истинного ключа достаточно проверить ключи из полученного множества на других парах открытый текст/шифртекст.&lt;br /&gt;
&lt;br /&gt;
==== Оптимизации ====&lt;br /&gt;
&lt;br /&gt;
1. От генерации второй таблицы со значениями &amp;lt;math&amp;gt;z_j^&#039;&amp;lt;/math&amp;gt; можно отказаться, перебирая ключи &amp;lt;math&amp;gt;k_2^j&amp;lt;/math&amp;gt; до того момента, когда значение &amp;lt;math&amp;gt;z_j^&#039;&amp;lt;/math&amp;gt; совпадёт с одним из значений &amp;lt;math&amp;gt;z_i&amp;lt;/math&amp;gt;. В таком случае опробование ключей &amp;lt;math&amp;gt;k_2^j&amp;lt;/math&amp;gt; в среднем сократится вдвое. Также вдвое сократится объём используемой памяти. Для нахождения совпадающего значения в отсортированном массиве можно применить бинарный поиск.&lt;br /&gt;
&lt;br /&gt;
2. Вместо сортировки таблицы со значениями &amp;lt;math&amp;gt;z_i&amp;lt;/math&amp;gt; и последующего бинарного поиска можно использовать хэш-таблицу.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
В случае использования хэш-таблицы достаточно большого размера основную сложность алгоритма составляет опробование ключей &amp;lt;math&amp;gt;k_1,k_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
Одним из самых трудоёмких шагов также оказывается сортировка таблицы.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Как видно из описания, атака &amp;quot;встреча посередине&amp;quot; использует (или может использовать в качестве оптимизации) следующие алгоритмы:&lt;br /&gt;
&lt;br /&gt;
1. Алгоритм зашифрования/расшифрования&lt;br /&gt;
&lt;br /&gt;
2. Алгоритм сортировки&lt;br /&gt;
&lt;br /&gt;
3. Алгоритмы поиска, вставки в хэш-таблицу&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Далее приводится последовательность действий для варианта алгоритма с генерацией одной таблицы значений &amp;lt;math&amp;gt;z_i&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
1. Вычислить таблицу &amp;lt;math&amp;gt;z_i&amp;lt;/math&amp;gt;, записывая значения в порядке вычисления или используя хэш-таблицу&lt;br /&gt;
&lt;br /&gt;
2. В случае записи значений в порядке вычисления отсортировать массив&lt;br /&gt;
&lt;br /&gt;
3. Опробовать ключи &amp;lt;math&amp;gt;k_2^j&amp;lt;/math&amp;gt;, ища совпадения с таблицей значений &amp;lt;math&amp;gt;z_j^&#039;&amp;lt;/math&amp;gt;. Для нахождения совпадения использовать поиск по хэш-таблице (если она есть) или бинарный поиск&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
Всюду далее считаем, что алгоритм не прекращает работу при нахождении первого совпадения, а ищет все совпадения.&lt;br /&gt;
&lt;br /&gt;
1. Сложность вычисления таблиц значений &amp;lt;math&amp;gt;z_i,z_j^&#039;&amp;lt;/math&amp;gt; составит &amp;lt;math&amp;gt;O(|K_1|+|K_2|)&amp;lt;/math&amp;gt; операций опробования &lt;br /&gt;
&lt;br /&gt;
2. Объединение таблиц и их сортировка будет иметь сложность &amp;lt;math&amp;gt;O((|K_1|+|K_2|)\log(|K_1|+|K_2|))&amp;lt;/math&amp;gt; (например, при сортировке слиянием).&lt;br /&gt;
&lt;br /&gt;
3. Сложность бинарного поиска в отсортированном массиве — &amp;lt;math&amp;gt;O(log_2(|K_1|))&amp;lt;/math&amp;gt; для каждого поиска&lt;br /&gt;
&lt;br /&gt;
4. Сложность поиска в достаточно большой хэш-таблице составит &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt; для каждого поиска&lt;br /&gt;
&lt;br /&gt;
Итого асимптотическая сложность алгоритма:&lt;br /&gt;
&lt;br /&gt;
1. С генерацией двух таблиц — &amp;lt;math&amp;gt;O(|K_1|+|K_2|) + O((|K_1|+|K_2|)\log(|K_1|+|K_2|)) + O(|K_1|+|K_2|)=O((|K_1|+|K_2|)\log(|K_1|+|K_2|))&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. C генерацией одной таблицы, сортировкой и бинарным поиском — &amp;lt;math&amp;gt;O(|K_1|) + O((|K_1|)\log(|K_1|)) + O(|K_2|\log_2(|K_1|))=O(max(|K_1|,|K_2|)\log(|K_1|))&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
3. C генерацией одной (достаточно большой) хэш-таблицы — &amp;lt;math&amp;gt;O(|K_1|) + O(|K_2|)=O(|K_1|+|K_2|)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть n - количество всевозможных пар &amp;lt;math&amp;gt;k_1,k_2&amp;lt;/math&amp;gt; и пусть &amp;lt;math&amp;gt;|K_1|=|K_2|&amp;lt;/math&amp;gt;. В этом случае &amp;lt;math&amp;gt;|K_1|=|K_2|=\sqrt n&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Тогда сложность алгоритма в первых двух пунктах составляет &amp;lt;math&amp;gt;O(\sqrt n\log(n))&amp;lt;/math&amp;gt;, в третьем — &amp;lt;math&amp;gt;O(\sqrt n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
&lt;br /&gt;
Опишем информационный граф алгоритма. На вход подаётся открытый (Open) и закрытый (Close), т.е. зашифрованный, текст. Далее открытый текст шифруется (Enc) на ключах &amp;lt;math&amp;gt;k_1^i&amp;lt;/math&amp;gt;, а зашифрованный расшифровывается (Dec) на ключах &amp;lt;math&amp;gt;k_2^j&amp;lt;/math&amp;gt;. Далее полученные криптограммы сравниваются (Cmp) и все ключи, на которых они совпали, являются выходом алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[file:meet.png|thumb|center|1040px|Рисунок 1. Граф алгоритма c отображением входных и выходных данных. Open — открытый текст, Close — шифртекст, Enc — операция зашифрования, Dec — операция расшифрования, Cmp — операция сравнения, Keys — вычисленные ключи]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Как видно из информационного графа, для реализации атаки &amp;quot;встреча посередине&amp;quot; в параллельном варианте потребуются выполнение следующих двух ярусов (в предположении, что &amp;lt;math&amp;gt;|K_1|=|K_2|&amp;lt;/math&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
1. &amp;lt;math&amp;gt;\sqrt n&amp;lt;/math&amp;gt; зашифрований и столько же расшифрований&lt;br /&gt;
&lt;br /&gt;
2. &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; сравнений&lt;br /&gt;
&lt;br /&gt;
Таким образом, высота ЯПФ составляет 2, ширина - &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вход:&#039;&#039;&#039;&lt;br /&gt;
На вход подаётся открытый текст &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; и шифртекст &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt;, а также алгоритм зашифрования/расшифрования. В случае блочного шифра открытым текстом и шифртекстом является последовательность блоков. Для атаки &amp;quot;встреча посередине&amp;quot;, как правило, берётся один блок для максимального ускорения операций зашифрования и расшифрования.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выход:&#039;&#039;&#039;&lt;br /&gt;
Результатом работы алгоритма является множество пар &amp;lt;math&amp;gt;k_1^i,k_2^j&amp;lt;/math&amp;gt;, для которых нашлись совпадения. Только одна из пар является настоящим ключом. Чтобы отсеять лишние, необходимо проверить все пары на блоках открытого и шифрованного текста, которые в алгоритме не использовались.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
Соотношением последовательной и параллельной сложности алгоритма является &amp;lt;math&amp;gt;O(\sqrt n\log(n))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Будем считать, что размер входных данных (открытый текст и шифртекст) совпадает с размером ключа (на практике это сравнимые величины), а сортировка слиянием делит массивы пополам. Тогда вычислительная мощность алгоритма — &amp;lt;math&amp;gt;O(\sqrt n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Дуги информационного графа, исходящие из вершин зашифрования и расшифрования, образуют пучки мощности &amp;lt;math&amp;gt;\sqrt n&amp;lt;/math&amp;gt;, т.е. из каждой такой вершины выходит &amp;lt;math&amp;gt;\sqrt 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;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Одна из реализаций атаки &amp;quot;встреча посередине&amp;quot; с использованием хэш-таблицы представлена в свободном доступе по ссылке [https://gist.github.com/dchest/1062437 github]&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;/div&gt;</summary>
		<author><name>Algoman</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%9C%D0%B0%D1%80%D0%B8%D1%8F_%D0%93%D0%BE%D1%82%D0%BC%D0%B0%D0%BD&amp;diff=15107</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%9C%D0%B0%D1%80%D0%B8%D1%8F_%D0%93%D0%BE%D1%82%D0%BC%D0%B0%D0%BD&amp;diff=15107"/>
		<updated>2016-10-31T14:04:17Z</updated>

		<summary type="html">&lt;p&gt;Algoman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Замечания к [[Алгоритм_кластеризации,_основанный_на_максимизации_ожидания]] ==&lt;br /&gt;
&lt;br /&gt;
1) список литературы лучше оформить средствами разметки - см. как сделано в [[Разложение_Холецкого_(метод_квадратного_корня)]]&lt;br /&gt;
&lt;br /&gt;
Список литературы исправлен.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Замечения от 31.10 ==&lt;br /&gt;
&lt;br /&gt;
&amp;quot;- В конце статьи должен быть приведен список всех источников, откуда бралась информация по алгоритму. Если вы используется готовый рисунок, то сслыку на источник нужно разместить либо в подписи к рисунку, либо в тексте, где стоит ссылка на рисунок.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
какой источник картинок с графиками (п1.1 и 2.4)? созданы ли они авторами для этой статьи, публиковались ли где-то ещё?&lt;/div&gt;</summary>
		<author><name>Algoman</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:Noite/EM-%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8&amp;diff=15106</id>
		<title>Участник:Noite/EM-алгоритм кластеризации</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:Noite/EM-%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8&amp;diff=15106"/>
		<updated>2016-10-31T14:03:40Z</updated>

		<summary type="html">&lt;p&gt;Algoman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Algoman}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = EM-алгоритм кластеризации&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n * m^2 * k)&amp;lt;/math&amp;gt; - одна итерация&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n * m + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Автор описания: [[Участник:Noite|Зинченко Д.А.]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритма =&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
В задачах оптимизации EM-алгоритмом называют итеративную процедуру поиска численного значения экстремума какой-либо функции. В частности, в статистике этот алгоритм используется для оценки максимального правдоподобия. Впервые название EM-алгоритм было предложено в 1977 году&amp;lt;ref&amp;gt;A. Dempster, N. Laird and D. Rubin. Maximum likelihood estimation from incomplete data. – Journal of the Royal Statistical Society, Series B, 1977, vol. 39, p. 1-38.&amp;lt;/ref&amp;gt;, однако его идеи были описаны и раньше&amp;lt;ref name=korolev&amp;gt;В.Ю.Королёв. ЕМ-алгоритм, его модификации и их применение к задаче разделения смесей вероятностных распределений.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
EM-алгоритм применяется для решения задач двух типов &amp;lt;ref name=korolev/&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
# Анализ неполных данных (данных с пропусками). &lt;br /&gt;
# Оценка максимального правдоподобия в случае, если функцию правдоподобия трудно исследовать аналитически. В этом случае введение набора скрытых переменных может существенно упростить задачу.&lt;br /&gt;
&lt;br /&gt;
Задача кластеризации относится к задачам второго типа. В данной статье рассматривается следующая постановка задачи кластеризации:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;Дано множество объектов, каждый из которых представляет собой точку в n-мерном метрическом пространстве. Каждому измерению пространства соответствует некоторое свойство объекта. Необходимо разбить это множество на k подмножеств так, чтобы, чтобы элементы каждого подмножества существенно отличались по свойствам от элементов других подмножеств.&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Использование алгоритма EM подразумевает следующее &#039;&#039;предположение об объектах&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
Пусть объекты, которые необходимо разбить на кластеры, появляются случайным образом и независимо друг от друга согласно вероятностному распределению, равному смеси (линейной комбинации) распределений кластеров. В данной статье в дальнейшем будет считаться, что распределение каждого кластера является многомерным нормальным распределением с произвольной матрицей ковариации - наиболее часто используемое предположение.&lt;br /&gt;
&lt;br /&gt;
Тогда каждый объект принадлежит каждому кластеру, но с разной вероятностью. EM-алгоритм итеративно оценивает параметры распределений кластеров, максимизируя логарифмическую функцию максимального правдоподобия. После окончания работы алгоритма объект будет отнесен к кластеру, вероятность принадлежности которому максимальна. Вводимый набор скрытых переменных для каждого объекта - вероятности того, что объект принадлежит каждому из кластеров.&lt;br /&gt;
&lt;br /&gt;
Итерация алгоритма состоит из двух последовательных шагов.&lt;br /&gt;
&lt;br /&gt;
# (Expectation) Вычисляются новые ожидаемые значения скрытых переменных.&lt;br /&gt;
# (Maximization) Решается задача максимизации правдоподобия: По текущим значениям скрытых переменных обновляются параметры распределений для кластеров: математическое ожидание, дисперсия и вероятность появления объектов из кластера.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Используемые обозначения:&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - количество объектов, &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; - количество кластеров, &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - количество параметров объекта&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\gamma_{n,k}&amp;lt;/math&amp;gt; - значения скрытых переменных&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;N_{k}&amp;lt;/math&amp;gt; - количество элементов отнесенных к соответствующему кластеру&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;x_{1},...,x_n&amp;lt;/math&amp;gt; - объекты&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Параметры распределений:&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;w_{1},...,w_{k}&amp;lt;/math&amp;gt; - вероятности появления объектов из кластеров (веса кластеров), &amp;lt;math&amp;gt;\sum_{k=1}^Kw_{k}=1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\mu_{1},...,\mu_{k}&amp;lt;/math&amp;gt; - центры гауссиан кластеров&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\Sigma_{1},...,\Sigma_{k}&amp;lt;/math&amp;gt; - матрицы ковариации гауссиан кластеров, каждая матрица имеет размерность &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;x&amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Смесь распределений:&#039;&#039;&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt; P(x) = \sum_{j=1}^Kw_jp(x|\mu_{j}, \Sigma_{j})&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Цель алгоритма - вычислить параметры распределений, максимизирующих логарифм функции правдоподобия:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;\ln P(x|w,\mu,\Sigma)= \sum_{n=1}^N \ln \{ \sum_{k=1}^K w_{k}p(x_{n}|\mu_{k},\Sigma_{k})\}&amp;lt;/math&amp;gt;.&amp;lt;/center&amp;gt;  &lt;br /&gt;
&lt;br /&gt;
* В начале работы алгоритма задаются параметры начального приближения:&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;w_{i} = 1/K, \mu_{i} = random(x_{j}), i=1..K, j=1..N&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;\Sigma_{j,j}^{k}=\frac{1}{NK}\sum_{i=1}^N(x_{i,j} - \mu_{k,j})^2, k=1..K, j=1..M&amp;lt;/math&amp;gt;&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Поскольку от начального приближения может сильно зависеть результат работы алгоритма, вместо инициализации кластеров случайными центрами, равными весами и диагональными матрицами ковариации, как в приведенных формулах, часто применяют другие способы (подробнее - в [[#Особенности реализации последовательного алгоритма | особенностях реализации]])&#039;&#039;&lt;br /&gt;
* Далее итеративно выполняется следующая пара процедур:&lt;br /&gt;
** E-шаг: используя текущее значение параметров &amp;lt;math&amp;gt;w_{1},...,w_{k};\mu_{1},...,\mu_{k};\Sigma^{1},...,\Sigma^{k}&amp;lt;/math&amp;gt;, вычисляем значение вектора скрытых переменных &amp;lt;math&amp;gt;\gamma&amp;lt;/math&amp;gt;:&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;\gamma_{n,k}=\frac{w_{k}p(x_{n}|\mu_{k},\Sigma^{k})}{\sum_{j=1}^K w_{j}p(x_{n}|\mu_{j},\Sigma^{j})}, &amp;lt;/math&amp;gt; знаменатель дроби - нормировочный коэффициент&amp;lt;/center&amp;gt;&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;p(x|\mu,\Sigma)=\frac{1}{{(2\pi)}^{\frac{N}{2}}\sqrt{|\Sigma|}}exp\biggl\{-\frac{1}{2}{(x-\mu)}^T{\Sigma}^{-1}(x-\mu)\biggr\}&amp;lt;/math&amp;gt; - плотность &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;-мерного нормального распределения&amp;lt;/center&amp;gt;&lt;br /&gt;
** М-шаг: переоценка параметров по текущим значениям скрытых переменных для &amp;lt;math&amp;gt;k = 1..K&amp;lt;/math&amp;gt;:&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;\mu^{new}_{k}=\frac{1}{N_{k}}\sum_{n=1}^N \gamma_{n,k}x_{n}&amp;lt;/math&amp;gt;,&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;\Sigma_{new}^{k}=\frac{1}{N_{k}}\sum_{n=1}^N \gamma_{n,k} (x_{n}-\mu_{k}^{new})(x_{n}-\mu_{k}^{new})^{T}&amp;lt;/math&amp;gt;,&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&amp;lt;math&amp;gt;w_{k}^{new}=\frac{N_{k}}{N}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;N_{k}=\sum_{n=1}^N \gamma_{n,k}&amp;lt;/math&amp;gt;.&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В EM алгоритме используется один из следующих критериев остановки:&lt;br /&gt;
*Норма разности векторов скрытых переменных на текущей итерации не превышает заданную константу &lt;br /&gt;
*Прошествие заданного количества итераций&lt;br /&gt;
*Изменение логарифмического правдоподобия меньше заданной константы.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро алгоритма состоит из двух шагов, повторяющихся каждую итерацию:&lt;br /&gt;
*Обновление скрытых переменных на основе текущих параметров распределений&lt;br /&gt;
*Обновление параметров кластеров: весов, центров и матриц ковариации&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как записано в [[#Вычислительное ядро алгоритма|описании вычислительного ядра алгоритма]], основную часть алгоритма составляют итеративно проводимые макрооперации: Expectation шаг - вычисление новых значений скрытых переменных, Maximization шаг - обновление параметров кластеров. Макроструктура алгоритма представлена на рисунке 1:&lt;br /&gt;
[[file:EM_macro.png|thumb|center|600px|Рисунок 1: Макроструктура EM-алгоритма]]&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Примерная схема реализации EM алгоритма с предварительной обработкой матриц ковариации:&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
// n - количество объектов&lt;br /&gt;
&lt;br /&gt;
// m - количество координат объектов&lt;br /&gt;
&lt;br /&gt;
// k - количество кластеров&lt;br /&gt;
&lt;br /&gt;
Инициализировать веса и центры кластеров;&lt;br /&gt;
Инициализировать матрицы ковариации;&lt;br /&gt;
&lt;br /&gt;
// Основной цикл&lt;br /&gt;
Пока условие остановки не выполнено&lt;br /&gt;
    // E-шаг&lt;br /&gt;
    В цикле для каждого кластера&lt;br /&gt;
        Вычислить определитель матрицы ковариации Sigma;&lt;br /&gt;
        Вычислить обратную матрицу матрице Sigma;&lt;br /&gt;
    В цикле для каждого объекта&lt;br /&gt;
        В цикле для каждого кластера&lt;br /&gt;
            Вычислить и запомнить p(x | mu, Sigma) для текущего объекта и кластера;&lt;br /&gt;
            Просуммировать вычисленные p(x | mu, Sigma);&lt;br /&gt;
        В цикле для каждого кластера&lt;br /&gt;
            Обновить скрытые переменные gamma;&lt;br /&gt;
    // M-шаг&lt;br /&gt;
    Обновить веса w;&lt;br /&gt;
    Обновить центры кластеров mu;&lt;br /&gt;
    Обновить матрицы ковариации Sigma;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Количество итераций алгоритма зависит от условия остановки, поэтому будем рассматривать сложность одной итерации.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Шаг E&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Сложность вычисления определителя произвольной матрицы ковариации &amp;lt;math&amp;gt;\Sigma&amp;lt;/math&amp;gt; методом Гаусса - &amp;lt;math&amp;gt;O(m^3)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Сложность вычисления матрицы, обратной произвольной матрице ковариации &amp;lt;math&amp;gt;\Sigma&amp;lt;/math&amp;gt; методом Гаусса - &amp;lt;math&amp;gt;O(m^3)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Сложность предварительного вычисления определителей и обратных матриц матрицам ковариации - &amp;lt;math&amp;gt;O(k * m^3)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С учетом заранее вычисленных определителей и обратных матриц сложность вычисления &amp;lt;math&amp;gt;p(x | \mu,\Sigma)&amp;lt;/math&amp;gt; составит: &amp;lt;math&amp;gt;O(m^2)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Суммарно сложность шага E составит &amp;lt;math&amp;gt;O(n * m^2 * k + k * m^3)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Шаг M&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Сложность обновления весов кластеров &amp;lt;math&amp;gt;O(k * n)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Сложность обновления центров кластеров &amp;lt;math&amp;gt;O(k * m * n)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Сложность обновления одной матрицы ковариации &amp;lt;math&amp;gt;O(n * m)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Сложность обновления всех матриц ковариации &amp;lt;math&amp;gt;O(k * m * n)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
Суммарно сложность шага M алгоритма - &amp;lt;math&amp;gt;O(k * m * n)&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Таким образом, сложность одной итерации EM алгоритма для псевдокода, указанного в предыдущем разделе, составит &amp;lt;math&amp;gt;O(k * m^2 * n + k * m^3 + k * m * n)&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
В предположении, что размерность объектов много меньше их количества &amp;lt;math&amp;gt;m &amp;lt;&amp;lt; n&amp;lt;/math&amp;gt; получим сложность итерации &amp;lt;math&amp;gt;O(k * m^2 * n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что вычисление определителя и обратной матрицы к произвольной матрице ковариации составляет большУю часть работы шага E и существенно влияет на его сложность. Поэтому эти вычисления проведены заранее - вынесены за основной цикл шага E&amp;lt;ref name=ParallelEMComparissonGraphLab&amp;gt;Henggang Cui, Jinliang Wei, Wei Dai. Parallel Implementation of Expectation-Maximization for Fast Convergence - School of Computer Science, Carnegie Mellon University. [https://users.ece.cmu.edu/~hengganc/archive/report/final.pdf]&amp;lt;/ref&amp;gt;. Помимо этого сложность этих вычислений можно сократить еще сильнее, если ввести ограничения структуру матрицы ковариации &amp;lt;math&amp;gt;\Sigma&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Наиболее часто используемым ограничением, позволяющим эффективно распараллеливать алгоритм&amp;lt;ref&amp;gt;Вячеслав Орешков. EМ — масштабируемый алгоритм кластеризации [https://basegroup.ru/community/articles/em]&amp;lt;/ref&amp;gt;, является предположение, что матрица ковариации имеет диагональную форму. Тогда вычисление её определителя и обратной матрицы имеет сложнось &amp;lt;math&amp;gt;O(m)&amp;lt;/math&amp;gt;, а суммарная сложность шага E и сложность всей итерации составит &amp;lt;math&amp;gt;O(k * m * n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
Макроструктура алгоритма представлена на рисунке 1 (см. [[#Макроструктура алгоритма|раздел 1.4]] статьи).&lt;br /&gt;
&lt;br /&gt;
На рисунке 2 представлена схема вычислений E-шага алгоритма для одного объекта: для объекта &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; и параметров &amp;lt;math&amp;gt;w_{j}, \mu_{j}, \Sigma_{j}, j=1..k&amp;lt;/math&amp;gt; по формулам [[#Математическое описание алгоритма|раздела 1.2]] вычисляются ненормированные значения скрытых переменных &amp;lt;math&amp;gt;g_{j}&amp;lt;/math&amp;gt;, нормировочный коэффициент &#039;&#039;normСoeff&#039;&#039;, и получаются итоговые значения &amp;lt;math&amp;gt;\gamma_{i,j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[file:EM_Expectation_step.png|thumb|center|400px|Рисунок 2: E-шаг EM алгоритма для одного объекта]]&lt;br /&gt;
&lt;br /&gt;
На рисунке 3 представлена схема вычислений E-шага алгоритма для всех объектов: для объекта &amp;lt;math&amp;gt;x_{j}&amp;lt;/math&amp;gt; и параметров-векторов &amp;lt;math&amp;gt;w, \mu, \Sigma&amp;lt;/math&amp;gt; по формулам [[#Математическое описание алгоритма|раздела 1.2]] вычисляются значения скрытых переменных. &amp;lt;math&amp;gt;E_{i}, i=1..n&amp;lt;/math&amp;gt; - маркооперации, E-шаги для соответствующих объектов.&lt;br /&gt;
&lt;br /&gt;
[[file:EM_Expectation_step_all.png|thumb|center|400px|Рисунок 3: E-шаг EM алгоритма для всех объектов]]&lt;br /&gt;
&lt;br /&gt;
На рисунке 4 представлена схема вычислений M-шага алгоритма для одного кластера: для объектов &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; и скрытых переменных &amp;lt;math&amp;gt;\gamma_{i,j}&amp;lt;/math&amp;gt;, соответствующих степени принадлежности этих объектов кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;, согласно формулам шага M [[#Математическое описание алгоритма|раздела 1.2]] вычисляется нормировочный коэффициент &amp;lt;math&amp;gt;N_{j}&amp;lt;/math&amp;gt; и параметры этого кластера: вес &amp;lt;math&amp;gt;w_{j}^{new}&amp;lt;/math&amp;gt;, матрица ковариации &amp;lt;math&amp;gt;\Sigma_{j}^{new}&amp;lt;/math&amp;gt; и центр кластера &amp;lt;math&amp;gt;\mu_{j}^{new}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[file:EM_Maximization_step.png|thumb|center|400px|Рисунок 4: M-шаг EM алгоритма для одного кластера]]&lt;br /&gt;
&lt;br /&gt;
На рисунке 5 представлена схема вычислений M-шага алгоритма для всех кластеров. &amp;lt;math&amp;gt;M_{j}, j=1..k&amp;lt;/math&amp;gt; соответствует макрооперации - M-шагу для соответствующего кластера и скрытых переменных.&lt;br /&gt;
&lt;br /&gt;
[[file:EM_Maximization_step_all.png|thumb|center|400px|Рисунок 5: M-шаг EM алгоритма для всех кластеров]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Из схем вычислений шагов E и M шагов алгоритма, приведенным в [[#Информационный граф|предыдущем разделе]], видно, что если размерность матрицы ковариации небольшая (тогда вычисление определителя и обратной матрицы матрице ковариации не является трудоемкой операцией), обе макрооперации EM алгоритма можно распараллеливать как по кластерам, так и по объектам.&lt;br /&gt;
&lt;br /&gt;
Как правило количество кластеров, на которые нужно разбить объекты, несравнимо меньше количества объектов, поэтому распараллеливание в большинстве существующих реализаций происходит по объектам: обработка объектов по возможности равномерно распределяются по кластерам. Теоретически (если считать передачу данных между процессорами мгновенной) при наличии неограниченного числа процессоров сложность алгоритма составит &amp;lt;math&amp;gt;O(m^2 * k)&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;k&amp;lt;/math&amp;gt; - количество кластеров;&lt;br /&gt;
* Значения координат объектов &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt; - &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; объектов с &amp;lt;math&amp;gt;m&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;n * m&amp;lt;/math&amp;gt; вещественных чисел (если координаты объектов - вещественные числа), &amp;lt;math&amp;gt;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;n&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;n&amp;lt;/math&amp;gt; целых неотрицательных чисел. &lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
=== Преимущества и недостатки&amp;lt;ref&amp;gt;EM алгоритм, его модификации и обобщения. machinelearning.ru [http://www.machinelearning.ru/wiki/index.php?title=EM-%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC]&amp;lt;/ref&amp;gt; ===&lt;br /&gt;
EM-алгоритм обладает следующими преимуществами и недостатками:&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;
&#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;
[[file:DifferentCovariance.png|thumb|center|800px|Рисунок 6: Влияние структуры матрицы ковариации на форму кластеров для двумерного случая. a) - матрицы ковариации являются диагональными, b) - матрицы ковариации произвольны. &amp;lt;ref&amp;gt;Mathworks: Clustering Using Gaussian Mixture Models [http://www.mathworks.com/help/stats/clustering-using-gaussian-mixture-models.html]&amp;lt;/ref&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Рисунок 6 наглядно показывает, что при диагональной форме матриц ковариации полуоси эллипса (в общем случае - эллипсоида), соответствующего распределению объектов, отнесенных кластеру, параллельны осям координат объектов. В противном случае полуоси могут располагаться произвольным образом.&lt;br /&gt;
&lt;br /&gt;
=== Общие свойства ===&lt;br /&gt;
[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]] EM алгоритма равна &amp;lt;math&amp;gt;m * k * it&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - размерность объекта, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество кластеров, а &amp;lt;math&amp;gt;it&amp;lt;/math&amp;gt; - количество итераций. &lt;br /&gt;
&lt;br /&gt;
EM-алгоритм является итерационным, и число итераций в общем случае не фиксировано: оно зависит от условий остановки, начальных приближений и расположения объектов. Поэтому этот алгоритм &#039;&#039;недетерминированный&#039;&#039;. По тем же причинам EM-алгоритм является &#039;&#039;неустойчивым&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
=== Инициализация параметров распределений ===&lt;br /&gt;
Наиболее распространены 3 способа инициализации центров распределений для EM алгоритма:&lt;br /&gt;
# центр распределения совпадает со случайно выбранным объектом &amp;lt;math&amp;gt;x_{i}&amp;lt;/math&amp;gt;&lt;br /&gt;
# все наблюдения распределяются по кластерам случайным образом, а затем для каждого кластера пересчитывается цент соответствующего распределения&lt;br /&gt;
# центры кластеров получаются в результате работы алгоритма k-means. Использование такой инициализации оправдано тем, что k-means требует меньших вычислительных затрат и быстрее сходится&amp;lt;ref&amp;gt;EM алгоритм (пример) machinelearning.ru [http://www.machinelearning.ru/wiki/index.php?title=EM_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_(%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80])&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;
Многие статьи&amp;lt;ref name=FREERIDE&amp;gt;Leonid Glimcher, Gagan Agrawal. Parallelising EM Algorithm on a Cluster of SMPs [http://web.cse.ohio-state.edu/~agrawal/allpapers/europar04.pdf]&amp;lt;/ref&amp;gt;&amp;lt;ref name=CV&amp;gt;López-de-Teruel P. E., García J. M., Acacio; The Parallel EM Algorithm and its Applications in Computer Vision [http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.4.8470&amp;amp;rep=rep1&amp;amp;type=pdf]&amp;lt;/ref&amp;gt;&amp;lt;ref name=MULTITHREAD&amp;gt;Sharon X. Lee, Kaleb L. Leemaqz, Geoffrey J. McLachlan. A simple multithreaded implementation of the EM algorithm for mixture models [https://arxiv.org/pdf/1606.02054.pdf]&amp;lt;/ref&amp;gt;&amp;lt;ref name=CUDA&amp;gt;Araújo, G.F., H.T. Macedo, M.T. Chella, C.A.E. Montesco and M.V.O. Medeiros. PARALLEL IMPLEMENTATION OF EXPECTATION-MAXIMISATION ALGORITHM FOR THE TRAINING OF GAUSSIAN MIXTURE MODELS [https://ri.ufs.br/bitstream/123456789/1764/1/ExpectationMaximisationAlgorithm.pdf]&amp;lt;/ref&amp;gt;, в которых представлены параллельные реализации EM алгоритма, описывают помимо использующихся программных и аппаратных решений результаты проведенных экспериментов с данными. В качестве примера в этом разделе будут рассмотрены результаты эксперементов, проведенных со связующим программным обеспечением (&#039;&#039;middleware&#039;&#039;) FREERIDE&amp;lt;ref&amp;gt;Leonid Glimchera, Ruoming Jinb, Gagan Agrawala. Middleware for data mining applications on clusters and grids [http://www.cs.kent.edu/~jin/Papers/JPDC08.pdf]&amp;lt;/ref&amp;gt; (FRamework for Rapid Implementation of Datamining Engines), обеспечивающим возможность распараллеливания как для систем с общей памятью (в частности, симметричных мультипроцессорных систем), так и для систем с распределенной памятью.&lt;br /&gt;
&lt;br /&gt;
Эксперименты проводились на кластере машин Pentium 700MHz связанных при помощи Myrinet&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Myrinet&amp;lt;/ref&amp;gt; LANai 7.0 на трех наборах данных: &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;а)&#039;&#039;&#039; 3.3 * 10^6 объектов&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;b)&#039;&#039;&#039; 6.2 * 10^6 объектов&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;c)&#039;&#039;&#039; 12.5 * 10^6 объектов&lt;br /&gt;
&lt;br /&gt;
Объекты представляют собой координаты точек 10-мерного пространства.&lt;br /&gt;
 &lt;br /&gt;
Количество машин в кластере варьировалось от 1 до 8, при этом на каждой машине запускалось до четырех параллельных потоков.&lt;br /&gt;
&lt;br /&gt;
Результаты экспериментов представлены на рисунках 7-9&amp;lt;ref name=FREERIDE/&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
{|align=&amp;quot;center&amp;quot;&lt;br /&gt;
 |-valign=&amp;quot;top&amp;quot;&lt;br /&gt;
 |[[file:EM_FREERIDE_experiments_a.png|thumb|center|350px|Рисунок 7: набор данных a)]]&lt;br /&gt;
 |[[file:EM_FREERIDE_experiments_b.png|thumb|center|357px|Рисунок 8: набор данных b)]]&lt;br /&gt;
 |[[file:EM_FREERIDE_experiments_c.png|thumb|center|351px|Рисунок 9: набор данных c)]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
Несмотря на то, что используемые в данном исследовании машины, как и коммуникационная среда, сейчас не используются и считаются устаревшими, результат приведенных экспериментов наглядно показывает, что EM алгоритм хорошо параллелится, зависимость ускорения от числа узлов в кластере с небольшим количеством узлов близка к линейной, а также, что скорость работы алгоритма линейно зависит от числа объектов.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&#039;&#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;
Примеры библиотек, содержащих последовательную реализацию EM-алгоритма, или отдельных реализаций:&lt;br /&gt;
&lt;br /&gt;
# [http://docs.opencv.org/2.4/modules/ml/doc/expectation_maximization.html OpenCV(C++)] ([https://github.com/opencv/opencv/blob/master/modules/ml/src/em.cpp github])&lt;br /&gt;
# [http://www.mathworks.com/help/stats/clustering-using-gaussian-mixture-models.html Matlab]&lt;br /&gt;
# [http://scikit-learn.org/stable/modules/mixture.html Scikit learn (Python)]&lt;br /&gt;
# [http://mlpack.org/index.html MLPack(C++)]&lt;br /&gt;
&lt;br /&gt;
Примеры библиотек, содержащих параллельную реализацию EM-алгоритма, или отдельных реализаций:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Здесь приводятся как конкретные реализации, так и статьи, описывающие подходы к реализациям распараллеливания EM-алгоритма&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
# [https://spark.apache.org/ Apache Spark]&lt;br /&gt;
# [http://accord-framework.net/ Accord.NET Framework (C#)]&lt;br /&gt;
# Статья об использовании FREERIDE middleware для распараллеливания EM алгоритма &amp;lt;ref name=FREERIDE/&amp;gt; &lt;br /&gt;
# [http://andrewharp.com/gmmcuda реализация с использованием CUDA]&lt;br /&gt;
# [https://github.com/Corv/CUDA-GMM-MPI еще одна реализация с использованием CUDA]&lt;br /&gt;
# статья об использовании параллельного EM алгоритма в задачах компьютерного зрения &amp;lt;ref name=CV/&amp;gt;&lt;br /&gt;
# статья о распараллеливании EM алгоритма с использованием CUDA &amp;lt;ref name=CUDA/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Algoman</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%9C%D0%B0%D1%80%D0%B8%D1%8F_%D0%93%D0%BE%D1%82%D0%BC%D0%B0%D0%BD/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8,_%D0%BE%D1%81%D0%BD%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9_%D0%BD%D0%B0_%D0%BC%D0%B0%D0%BA%D1%81%D0%B8%D0%BC%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BE%D0%B6%D0%B8%D0%B4%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=15103</id>
		<title>Участник:Мария Готман/Алгоритм кластеризации, основанный на максимизации ожидания</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9C%D0%B0%D1%80%D0%B8%D1%8F_%D0%93%D0%BE%D1%82%D0%BC%D0%B0%D0%BD/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8,_%D0%BE%D1%81%D0%BD%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9_%D0%BD%D0%B0_%D0%BC%D0%B0%D0%BA%D1%81%D0%B8%D0%BC%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BE%D0%B6%D0%B8%D0%B4%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=15103"/>
		<updated>2016-10-31T14:01:46Z</updated>

		<summary type="html">&lt;p&gt;Algoman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Авторы описания: [[Участник:Мария_Готман|Готман М.Л.]], [[Участник:Julia_lukashkina|Лукашкина Ю.Н.]]&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Задача кластеризации — это задача разбиения заданной входной выборки объектов на непересекающиеся подмножества, называемые кластерами, так, чтобы каждый кластер состоял из схожих объектов, а объекты разных кластеров существенно отличались. &lt;br /&gt;
&lt;br /&gt;
Для решения этой задачи можно использовать, например, метод максимизации ожидания, также известный как EM-алгоритм (англ. expectation-maximization) &amp;lt;ref&amp;gt;Воронцов К.В.; Математические методы обучения по прецедентам (теория обучения машин)&amp;lt;/ref&amp;gt;. В таком случае делается предположение, что входные данные — смесь многомерных нормальных распределений, соотвественно отдельный кластер — это одна компонента смеси. Предполагается, что количество кластеров является входным параметром алгоритма (существуют модификации EM-алгоритма, которые автоматически находят число кластеров, но они не рассматриваются в данной статье). Результат работы EM-алгоритма — веса кластеров и найденные параметры нормальных распределений для каждого кластера: вектора математических ожиданий и матрицы ковариации. &lt;br /&gt;
&lt;br /&gt;
Алгоритм EM кластеризации основан на итеративном выполнении двух последовательных шагов: E-шага и M-шага. На E-шаге вычисляеются вспомогательные (скрытые) переменные, которые характеризуют апостериорную вероятность того, что определенный обучающий объект получен из фиксированной компоненты смеси. На M-шаге с помощью вычесленных скрытых переменных производится обновление параметров смеси: по определённым формулам пересчитываются веса кластеров, их математические ожидания и матрицы ковариаций.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что на работу EM-алгоритма значительно влияет начальное приближение его параметров. При неудачной инициализации алгоритм может не сойтись или сойтись в локальный экстремум.&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается частный случай EM-алгоритма, который работает с двумерными входными данными.&lt;br /&gt;
&lt;br /&gt;
[[Файл:Em clusters 4.png|400px|thumb|center|Пример работы EM-алгоритма для 5ти кластеров.]]&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Рассматривается смесь нормальных распределений &amp;lt;math&amp;gt;p(x)=\sum_{j=1}^kw_jp_j(x), \sum_{j=1}^kw_j =1, w_j \ge 0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Алгоритм кластеризации, основанный на максимизации правдоподобия, итеративно выполняет два шага: E-шаг и M-шаг.&lt;br /&gt;
Идея алгоритма заключается в введении матрицы скрытых переменных &amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;g_{ij} \equiv P(\theta_j |x_i)&amp;lt;/math&amp;gt; обозначает вероятность принадлежности &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го объекта &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-му кластеру.&lt;br /&gt;
&lt;br /&gt;
На Е-шаге вычисляется ожидаемое значение скрытых переменных, на М-шаге выполняется максимизация логарифма полного правдоподобия, результатом которой являются новые значения параметров модели.&lt;br /&gt;
&lt;br /&gt;
На вход алгоритму подается матрица объектов-признаков &amp;lt;math&amp;gt;X \in \R^{m \times d}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; — количество кластеров.&lt;br /&gt;
&lt;br /&gt;
На выходе получаем набор параметров модели для каждого кластера &amp;lt;math&amp;gt;\Theta = (w_1,...,w_k;\;\mu_1,...,\mu_k;\;\Sigma_1,...,\Sigma_k)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;w_j&amp;lt;/math&amp;gt; — вес &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-го кластера в смеси нормальных распределений, &amp;lt;math&amp;gt;\mu_j&amp;lt;/math&amp;gt; — математическое ожидание &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-ой компоненты смеси, &amp;lt;math&amp;gt;\Sigma_j&amp;lt;/math&amp;gt; — матрица ковариации &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-ой компоненты смеси.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;E-шаг&amp;lt;/b&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;g_{ij} = \frac{w_jN(x_i;\mu_j, \Sigma_j)}{\sum_{s=1}^k w_sN(x_i;\mu_s, \Sigma_s)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;M-шаг&amp;lt;/b&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;Q(\Theta) = \ln\prod_{i=1}^mp(x_i) = \sum_{i=1}^m\ln\sum_{j=1}^kw_jp_j(x_i) \rightarrow \max_{\Theta}&amp;lt;/math&amp;gt;, при условии &amp;lt;math&amp;gt;\sum_{j=1}^kw_j=1&amp;lt;/math&amp;gt;, где&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;p_j(x_i) = N(x_i;\mu_j, \Sigma_j) = \frac1{(2\pi)^{d/2}\sqrt{|\Sigma_j|}} \exp \biggl(-\frac{1}{2}(x_i - \mu_j) \Sigma_j^{-1} (x_i - \mu_j)^T\biggr) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Решением оптимизационной задачи являются формулы для пересчета параметров:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;w_j = \frac1m\sum_{i=1}^m g_{ij}&amp;lt;/math&amp;gt;, &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\mu_j = \frac1{mw_j}\sum_{i=1}^m g_{ij}x_i&amp;lt;/math&amp;gt;, &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\Sigma_j = \frac1{mw_j}\sum_{i=1}^m g_{ij}(x_i - \mu_j)(x_i - \mu_j)^T,\; j = 1, \dots, k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро алгоритма представляет собой итерационное вычисление всех параметров модели, независимое по &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; объектам выборки &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt;.&lt;br /&gt;
На каждой итерации алгоритма на Е-шаге пересчитывается значение скрытых переменных, на M-шаге пересчет параметров модели с учетом скрытых переменных.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
Как записано в [[#Вычислительное ядро алгоритма|описании ядра алгоритма]], основную часть метода составляют вычисления элементов матрицы G на E шаге, и пересчет параметров &amp;lt;math&amp;gt;\Theta&amp;lt;/math&amp;gt; на M-шаге.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
# Инициализация параметров&lt;br /&gt;
# for iter = 1 : max_iterations&lt;br /&gt;
# [E-шаг]&lt;br /&gt;
## вычисление &amp;lt;math&amp;gt;\Sigma_j^{-1}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\frac1{(2\pi)^{d/2}\sqrt{|\Sigma_j|}}, j = 1 : k&amp;lt;/math&amp;gt;&lt;br /&gt;
## вычисление &amp;lt;math&amp;gt;g_{ij},\;i = 1 : m, \; j = 1 : k&amp;lt;/math&amp;gt;&lt;br /&gt;
## вычисление &amp;lt;math&amp;gt;LL_i&amp;lt;/math&amp;gt; (логарифм правдоподобия), &amp;lt;math&amp;gt;\;i = 1 : m&amp;lt;/math&amp;gt;&lt;br /&gt;
# [M-шаг]&lt;br /&gt;
## вычисление &amp;lt;math&amp;gt;\tilde w_j = \sum_{i=1}^m g_{ij}, \; j = 1 : m&amp;lt;/math&amp;gt;&lt;br /&gt;
## вычисление &amp;lt;math&amp;gt;\tilde \mu_j = \sum_{i=1}^m g_{ij}x_i,\; j = 1 : k&amp;lt;/math&amp;gt;&lt;br /&gt;
## вычисление &amp;lt;math&amp;gt;\tilde \Sigma_j = \sum_{i=1}^m g_{ij}(x_i - \mu_j)^T(x_i - \mu_j),\; j = 1 : k&amp;lt;/math&amp;gt;&lt;br /&gt;
## нормировка &amp;lt;math&amp;gt;w_j = \frac{\tilde w_j}{m}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\mu_j = \frac{\tilde \mu_j}{w_j}, \tilde \Sigma_j = \frac{\tilde \Sigma_j}{w_j}, \;j = 1 : k&amp;lt;/math&amp;gt;&lt;br /&gt;
# вычисление  изменения логарифма правдоподобия&amp;lt;math&amp;gt;\Delta LL&amp;lt;/math&amp;gt; &lt;br /&gt;
# if (&amp;lt;math&amp;gt;\Delta LL &amp;lt; \varepsilon&amp;lt;/math&amp;gt;) then break;&lt;br /&gt;
# end for&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&amp;lt;b&amp;gt;E-шаг&amp;lt;/b&amp;gt;:&lt;br /&gt;
# вычисление обратной матрицы &amp;lt;math&amp;gt;\Sigma_j^{-1}, j = 1 : k&amp;lt;/math&amp;gt; при фиксированном &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; для двумерного случая по явным формулам имеет сложность &amp;lt;math&amp;gt;O(d^2)&amp;lt;/math&amp;gt;, для всех кластеров — &amp;lt;math&amp;gt;O(d^2k)&amp;lt;/math&amp;gt;&lt;br /&gt;
# вычисление &amp;lt;math&amp;gt;g_{ij}, i = 1 : m, j = 1 : k&amp;lt;/math&amp;gt; при фиксированных &amp;lt;math&amp;gt;i, j&amp;lt;/math&amp;gt; имеет сложность &amp;lt;math&amp;gt;O(d)&amp;lt;/math&amp;gt;, сложность вычисления матрицы G — &amp;lt;math&amp;gt;O(dmk)&amp;lt;/math&amp;gt;&lt;br /&gt;
# вычисление &amp;lt;math&amp;gt;LL_i, i = 1 : m&amp;lt;/math&amp;gt; при фиксированном &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; имеет сложность &amp;lt;math&amp;gt;O(k)&amp;lt;/math&amp;gt;, для всех объектов имеет сложность &amp;lt;math&amp;gt;O(mk)&amp;lt;/math&amp;gt;,&lt;br /&gt;
&amp;lt;b&amp;gt;M-шаг&amp;lt;/b&amp;gt;:&lt;br /&gt;
# вычисление &amp;lt;math&amp;gt;w_j,  j = 1 : k&amp;lt;/math&amp;gt; при фиксированном &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; имеет сложность &amp;lt;math&amp;gt;O(m)&amp;lt;/math&amp;gt;, для весов всех кластеров — &amp;lt;math&amp;gt;O(mk)&amp;lt;/math&amp;gt;&lt;br /&gt;
# вычисление &amp;lt;math&amp;gt;\mu_j, j = 1 : k&amp;lt;/math&amp;gt; при фиксированном &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; имеет сложность &amp;lt;math&amp;gt;O(dm)&amp;lt;/math&amp;gt;, для всех кластеров — &amp;lt;math&amp;gt;O(dmk)&amp;lt;/math&amp;gt;&lt;br /&gt;
# вычисление &amp;lt;math&amp;gt;\Sigma_j, j = 1 : k&amp;lt;/math&amp;gt; при фиксированном &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; имеет сложность &amp;lt;math&amp;gt;O(d^2m)&amp;lt;/math&amp;gt;, для всех кластеров — &amp;lt;math&amp;gt;O(d^2mk)&amp;lt;/math&amp;gt;&lt;br /&gt;
# нормировка &amp;lt;math&amp;gt;w&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\mu_j = \frac{\mu_j}{w_j}, \Sigma_j = \frac{\Sigma_j}{w_j}, j = 1 : k&amp;lt;/math&amp;gt; имеет сложность &amp;lt;math&amp;gt;O(k)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;O(dk)&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;O(d^2k)&amp;lt;/math&amp;gt;&lt;br /&gt;
# вычисление  изменения логарифма правдоподобия&amp;lt;math&amp;gt;\Delta LL&amp;lt;/math&amp;gt; имеет сложность &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Сложность алгоритма на одной итерации&amp;lt;/b&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O(k(d^2+dm+m+m+dm+d^2m+1+d+d^2)) = O(d^2mk)&amp;lt;/math&amp;gt;, так как мы рассматриваем задачу для двумерного случая, то есть &amp;lt;math&amp;gt;d=2&amp;lt;/math&amp;gt;, множитель &amp;lt;math&amp;gt;d^2&amp;lt;/math&amp;gt; можно отнести в константу, итоговая сложность вычисления на одной итерации &amp;lt;math&amp;gt;O(mk)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Для &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; итераций итоговая сложность алгоритма будет равна&amp;lt;/b&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;O(mkn)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; — число объектов, &amp;lt;math&amp;gt;k&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;
Опишем граф алгоритма для следующих входных данных: &amp;lt;math&amp;gt;m = 3,\; k = 2,\; d = 2&amp;lt;/math&amp;gt;, то есть 3 входных объекта и 2 кластера. &lt;br /&gt;
&lt;br /&gt;
На рис.1 показана макроструктура EM-алгоритма. Входными данными в таком случае являются матрица &amp;lt;math&amp;gt;X \in \R^{3 \times 2}&amp;lt;/math&amp;gt; и число кластеров &amp;lt;math&amp;gt;k = 2&amp;lt;/math&amp;gt;. &lt;br /&gt;
На шаге &amp;lt;math&amp;gt;\mathbf{init}&amp;lt;/math&amp;gt; происходит инициализация начальных приближений параметров модели и затем итеративное повторение &amp;lt;math&amp;gt;\mathbf{E}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\mathbf{M}&amp;lt;/math&amp;gt; шагов алгоритма. &lt;br /&gt;
&lt;br /&gt;
[[file:EM.png|thumb|center|300px|Рис.1. Граф EM-алгоритма с отображением входных и выходных данных]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;E-шаг.&amp;lt;/b&amp;gt; На рис.2 детально изображена схема E-шага. &lt;br /&gt;
Входные параметры &amp;lt;math&amp;gt;x_1,\; x_2,\; x_3 \in \R^{1 \times 2}&amp;lt;/math&amp;gt; являются строчками входной матрицы &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt;, также на вход подаются текущие приближения векторов средних значений (&amp;lt;math&amp;gt;\mu_1, \;\mu_2&amp;lt;/math&amp;gt;), матриц ковариаций (&amp;lt;math&amp;gt;\Sigma_1, \Sigma_2&amp;lt;/math&amp;gt;) и весов &amp;lt;math&amp;gt;w&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Вершинами &amp;lt;math&amp;gt;\mathbf{eI}&amp;lt;/math&amp;gt; обозначена операция нахождения обратной матрицы &amp;lt;math&amp;gt;\Sigma_j^{-1},\; j = 1,2&amp;lt;/math&amp;gt;. Вершины группы &amp;lt;math&amp;gt;\mathbf{eS}&amp;lt;/math&amp;gt; обозначают вычитание векторов &amp;lt;math&amp;gt;x_i - \mu_j,\; i = 1,2,3; \; j = 1, 2&amp;lt;/math&amp;gt;. Салатовые узлы графа &amp;lt;math&amp;gt;\mathbf{eE}&amp;lt;/math&amp;gt; обозначают вычисление ненормированного значения &amp;lt;math&amp;gt;g_{ij}, \;i = 1,2,3;\;j=1,2&amp;lt;/math&amp;gt; по формулам из раздела [[#Схема реализации последовательного алгоритма|описания алгоритма]]. Далее выход вершин этой группы подаётся на вход вершинам &amp;lt;math&amp;gt;\mathbf{eN}&amp;lt;/math&amp;gt;, которые обозначают нормировку, затем в &amp;lt;math&amp;gt;\mathbf{eL}&amp;lt;/math&amp;gt; происходит подсчет логарифма правдоподобия. На выходе этого графа получаются скрытые переменные &amp;lt;math&amp;gt;g_{ij}&amp;lt;/math&amp;gt; и логарифм правдоподобия LL.&lt;br /&gt;
 &lt;br /&gt;
[[file:EM_E_step.png|thumb|center|500px|Рис.2. Граф E-шага с отображением входных и выходных данных]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;M-шаг.&amp;lt;/b&amp;gt; На рисунке 3 изображена схема M-шага.&lt;br /&gt;
Входными параметрами являются: исходные объекты &amp;lt;math&amp;gt;x_1,\; x_2,\; x_3 \in \R^{1 \times 2}&amp;lt;/math&amp;gt;, скрытые переменные &amp;lt;math&amp;gt;g_{11},\;g_{21},\;g_{31},\;\mu_1&amp;lt;/math&amp;gt; для пересчета параметров первого кластера и &amp;lt;math&amp;gt;g_{12},\;g_{22},\;g_{32},\;\mu_2&amp;lt;/math&amp;gt; — для второго.&lt;br /&gt;
&lt;br /&gt;
Вершина &amp;lt;math&amp;gt;\mathbf{m}\boldsymbol{\mu}&amp;lt;/math&amp;gt; обозначает подсчет слагаемого математического ожидания для одного объекта, затем на шаге &amp;lt;math&amp;gt;\mathbf{mS_1}&amp;lt;/math&amp;gt; происходит суммирование слагаемых, и, наконец, на шаге &amp;lt;math&amp;gt;\mathbf{mN_1}&amp;lt;/math&amp;gt; нормировка математического ожидания, выходом являются &amp;lt;math&amp;gt;\mu_1,\;\mu_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
Вершина &amp;lt;math&amp;gt;\mathbf{m}\boldsymbol{\Sigma}&amp;lt;/math&amp;gt; обозначает подсчет слагаемого матрицы ковариации для одного объекта, затем на шаге &amp;lt;math&amp;gt;\mathbf{mS_2}&amp;lt;/math&amp;gt; происходит суммирование слагаемых, и, наконец, на шаге &amp;lt;math&amp;gt;\mathbf{mN_2}&amp;lt;/math&amp;gt; нормировка матрицы ковариации, выходом являются &amp;lt;math&amp;gt;\Sigma_1,\;\Sigma_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
Операция &amp;lt;math&amp;gt;\mathbf{mS_3}&amp;lt;/math&amp;gt; обозначает вычисление ненормированного веса для одного шага, затем при выполнении &amp;lt;math&amp;gt;\mathbf{mN_3}&amp;lt;/math&amp;gt; происходит нормировка весов, выходом являются &amp;lt;math&amp;gt;w_1,\;w_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[file:EM_M_step.png|thumb|center|500px|Рис.3. Граф M-шага с отображением входных и выходных данных]]&lt;br /&gt;
&lt;br /&gt;
На рис.1 показана структура ЕM-алгоритма для кластеризации, на рис.2 — структура E-шага  и на рис.3 — структура M-шага.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Как видно из информационного графа, возможно распараллеливание как по кластерам, так и по объектам. Однако, в реальных задачах число кластеров много меньше числа объектов, поэтому распараллеливание по кластерам нецелесообразно.&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматривается вариант распараллеливания по объектам. Стоит отметить, что важно корректно организовать работу с параметрами модели (матрицами ковариаций, средними значениями и весами), чтобы не произошло ситуации гонки за ресурсами &amp;lt;ref&amp;gt;Воеводин В.В., Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: плотная вещественная матрица объекты-признаки &amp;lt;math&amp;gt;X \in \R^{m \times d}&amp;lt;/math&amp;gt;, количество кластеров &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;m \times d + 1&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: вектор весов &amp;lt;math&amp;gt;w \in \R^{k \times 1}&amp;lt;/math&amp;gt;,  &amp;lt;math&amp;gt;\;\;k&amp;lt;/math&amp;gt; векторов &amp;lt;math&amp;gt;\mu_j \in \R^{d \times 1}&amp;lt;/math&amp;gt;,  &amp;lt;math&amp;gt;\;\;k&amp;lt;/math&amp;gt; матриц &amp;lt;math&amp;gt;\Sigma \in \R^{d \times d}&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;k \times (d \times d + d + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Стоит заметить, что модель смеси распеределения полностью восстанавливается по выходным данным, и задача предсказания метки кластера для входных объектов является тривиальной.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]] алгоритма равна отношению числа операций к суммарному объему входных и выходных данных. Она показывает, сколько операций приходится на единицу переданных данных. Несмотря на простоту данного понятия, это значение исключительно полезно на практике: чем выше  вычислительная мощность, тем меньше накладных расходов вызывает перемещение данных для их обработки, например, на сопроцессоре, ускорителе или другом узле кластера. Например, вычислительная мощность скалярного произведения двух векторов равна всего лишь &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt;, а вычислительная мощность алгоритма умножения двух квадратных матриц равна &amp;lt;math&amp;gt;2n/3&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
EM-алгоритм не является устойчивым, результат его работы сильно зависит от начальных приближений параметров. При неудачном выборе начальных приближений алгоритм может не сойтись или сойтись  в локальный экстремум. &lt;br /&gt;
&lt;br /&gt;
Также, алгоритм не является детерминированным. Так как в начале работы алгоритма происходит инициализация начальных параметров случайным образом (с учетом положительной определенности и симметричности матрицы ковариации), он не может быть детерминирован.&lt;br /&gt;
&lt;br /&gt;
Алгоритм сбалансирован по E и M шагам, затраты на выполнение этих этапов примерно одинаковы.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
В данном разделе приведем код реализации последовательного алгоритма.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot;&amp;gt;&lt;br /&gt;
double_vector em_algo::expectation_step(double_matrix&amp;amp; features)&lt;br /&gt;
{&lt;br /&gt;
    long n_objects = features.size1();&lt;br /&gt;
    int n_clusters = parameters.sigmas.size();&lt;br /&gt;
    double pi = boost::math::constants::pi&amp;lt;double&amp;gt;();&lt;br /&gt;
&lt;br /&gt;
    // precalculate inverse matrices and dets&lt;br /&gt;
    std::vector&amp;lt;double_matrix&amp;gt; sigmas_inverted(n_clusters);&lt;br /&gt;
    std::vector&amp;lt;double&amp;gt; norm_distribution_denominator(n_clusters);&lt;br /&gt;
    for (int i = 0; i &amp;lt; n_clusters; ++i)&lt;br /&gt;
    {        &lt;br /&gt;
        double_matrix sigma_inverted(parameters.sigmas[i].size1(), parameters.sigmas[i].size2());&lt;br /&gt;
        double det = InvertMatrix(parameters.sigmas[i], sigma_inverted);&lt;br /&gt;
        if (det == 0)&lt;br /&gt;
        {&lt;br /&gt;
            std::cerr &amp;lt;&amp;lt; &amp;quot;Matrix can not be inverted\n&amp;quot;;&lt;br /&gt;
            exit(1);&lt;br /&gt;
        }&lt;br /&gt;
        norm_distribution_denominator[i] = sqrt(pow(2 * pi, parameters.n_features) * det);&lt;br /&gt;
        sigmas_inverted[i] = sigma_inverted;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    hidden_vars = double_matrix(n_objects, n_clusters);&lt;br /&gt;
    double_vector log_likelihood(n_objects, 0);&lt;br /&gt;
&lt;br /&gt;
    for (auto i = 0; i &amp;lt; n_objects; ++i)&lt;br /&gt;
    {&lt;br /&gt;
        double_matrix_row x(features, i);&lt;br /&gt;
        double norm_value = 0;&lt;br /&gt;
        for (auto j = 0; j &amp;lt; n_clusters; ++j)&lt;br /&gt;
        {&lt;br /&gt;
            double_matrix_column current_means(parameters.means, j);&lt;br /&gt;
            double_vector x_centered = x - current_means;&lt;br /&gt;
&lt;br /&gt;
            double exp_power = -0.5 * inner_prod(prod(x_centered, sigmas_inverted[j]), x_centered);&lt;br /&gt;
            hidden_vars(i, j) = parameters.weights(j) * exp(exp_power) / norm_distribution_denominator[j];&lt;br /&gt;
&lt;br /&gt;
            norm_value += hidden_vars(i, j);&lt;br /&gt;
        }&lt;br /&gt;
        double_matrix_row hidden_vars_row(hidden_vars, i);&lt;br /&gt;
        if (norm_value != 0)&lt;br /&gt;
        {&lt;br /&gt;
            hidden_vars_row = hidden_vars_row / norm_value;&lt;br /&gt;
            log_likelihood(i) = log(inner_prod(hidden_vars_row, parameters.weights));&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
    return log_likelihood;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void em_algo::maximization_step(double_matrix&amp;amp; features)&lt;br /&gt;
{&lt;br /&gt;
    int n_objects = features.size1();&lt;br /&gt;
&lt;br /&gt;
    double_vector w = double_vector(n_clusters, 0.0);&lt;br /&gt;
    double_matrix means = double_matrix(parameters.n_features, n_clusters, 0.0);&lt;br /&gt;
    std::vector&amp;lt;double_matrix&amp;gt; sigmas;&lt;br /&gt;
    for (int j = 0; j &amp;lt; n_clusters; ++j)&lt;br /&gt;
        sigmas.push_back(double_matrix(parameters.n_features, parameters.n_features, 0.0));&lt;br /&gt;
&lt;br /&gt;
    for (int i = 0; i &amp;lt; n_objects; ++i)&lt;br /&gt;
    {&lt;br /&gt;
        double_matrix_row x_i = row(features, i);&lt;br /&gt;
&lt;br /&gt;
        for (int j = 0; j &amp;lt; n_clusters; ++j)&lt;br /&gt;
        {&lt;br /&gt;
            double g = hidden_vars(i, j);&lt;br /&gt;
            w(j) += g;&lt;br /&gt;
&lt;br /&gt;
            double_matrix_column single_mean = column(means, j);&lt;br /&gt;
&lt;br /&gt;
            single_mean += g * x_i;&lt;br /&gt;
&lt;br /&gt;
            double_vector x_centered = x_i - column(parameters.means, j);&lt;br /&gt;
            for (int k = 0; k &amp;lt; parameters.n_features; ++k)&lt;br /&gt;
                for (int l = 0; l &amp;lt; parameters.n_features; ++l)&lt;br /&gt;
                    sigmas[j](k, l) = sigmas[j](k, l) + g * x_centered(k) * x_centered(l);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    // update weights&lt;br /&gt;
    parameters.weights = w / n_objects;&lt;br /&gt;
&lt;br /&gt;
    for (int j = 0; j &amp;lt; n_clusters; ++j) {&lt;br /&gt;
        double weight = w(j);&lt;br /&gt;
        // update means&lt;br /&gt;
        double_matrix_column means_old = column(parameters.means, j);&lt;br /&gt;
        double_matrix_column means_new = column(means, j);&lt;br /&gt;
        means_old = means_new / weight;&lt;br /&gt;
&lt;br /&gt;
        // update sigmas&lt;br /&gt;
        parameters.sigmas[j] = sigmas[j] / weight;&lt;br /&gt;
        for (int k = 0; k &amp;lt; parameters.n_features; ++k)&lt;br /&gt;
            parameters.sigmas[j](k, k) = parameters.sigmas[j](k, k) + tol;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
bool em_algo::is_likelihood_stabilized(double_vector likelihood, double_vector previous_likelihood)&lt;br /&gt;
{&lt;br /&gt;
    double likelihood_diff = sum(likelihood) - sum(previous_likelihood);&lt;br /&gt;
    return fabs(likelihood_diff) &amp;lt; tol;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
model em_algo::process(double_matrix&amp;amp; features, int max_iterations)&lt;br /&gt;
{&lt;br /&gt;
    int iteration = 0;&lt;br /&gt;
    double_vector likelihood, previous_likelihood;&lt;br /&gt;
    while (iteration++ &amp;lt; max_iterations &amp;amp;&amp;amp; (iteration &amp;lt;= 2 || !is_likelihood_stabilized(likelihood, previous_likelihood)))&lt;br /&gt;
    {&lt;br /&gt;
        previous_likelihood = likelihood;&lt;br /&gt;
        likelihood = expectation_step(features);&lt;br /&gt;
        maximization_step(features);&lt;br /&gt;
    }&lt;br /&gt;
    return parameters;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Возможной реализацией является перестановка местами циклов по объектам и по кластерам на E и М шаге. В данном случае внешний цикл проходит по объектам, так как подразумевается дальнейшая реализации распараллеливания по объектам. При реализации только последовательного алгоритма более понятной версией будет реализация внешнего цикла по кластерам, и внутреннего по объектам, но такая реализация увеличит число обращений в память и общее время работы алгоритма.&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;k = 4 &amp;lt;/math&amp;gt;, и, также, было зафиксировано ядро рандомизации, чтобы избавиться от случайности различного выбора начального приближения параметров. Для показательности результатов условие дострочного завершения работы алгоритма в случае стабилизирования логарифма правдоподобия игнорировалось, и для каждого запуска проводилось 50 итераций EM-алгоритма.&lt;br /&gt;
&lt;br /&gt;
Для экспериментов было сгенерировано 20 выборок разного размера: от 40000 объектов до 200000 с шагом в 10000. Для каждой выборки время работы алгоритма усреднялось по нескольким запускам, чтобы избежать выбросов.&lt;br /&gt;
&lt;br /&gt;
Для работы с многопоточностью использовалась библиотека OpenMP. С помощью нее были распараллелены основные циклы по объектам на E и M шаге.&lt;br /&gt;
&lt;br /&gt;
Эксперименты проводились на компьютере с процессором Intel(R) Core(TM) i7-5820K @ 3.30GHz, который поддерживает до 12ти потоков.&lt;br /&gt;
&lt;br /&gt;
Как видно на рис. 4, производительность растет до 12 процессов, после чего время работы алгоритма снова начинает увеличиваться, то есть использование более 12 процессов при рассматриваемой конфигурации процессора не имеет смысла. Заметим также, что в увеличением числа точек, скорость работы программы линейно увеличивается.&lt;br /&gt;
&lt;br /&gt;
[[file:EM performance.png|thumb|center|700px|Рис. 4 Время работы EM алгоритма в зависимости от числа процессов и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
В результате проведённых экспериментов был получен следующий диапазон эффективности реализации алгоритма:&lt;br /&gt;
&lt;br /&gt;
*	минимальная эффективность реализации 0,00072%;&lt;br /&gt;
*	максимальная эффективность реализации 25.5037%.&lt;br /&gt;
&lt;br /&gt;
[[file:EM_Efficiency.png|thumb|center|700px|Рис. 4 Эффективность EM алгоритма в зависимости от числа процессов и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
Существуют следующие последовательные реализации EM-алгоритма для кластеризации: [http://docs.opencv.org/2.4/modules/ml/doc/expectation_maximization.html# opencv], [http://scikit-learn.org/stable/modules/mixture.html scikit-learn]. &lt;br /&gt;
&lt;br /&gt;
Также существует несколько параллельных реализаций, описанных в следующих статьях:&lt;br /&gt;
&lt;br /&gt;
В статье &amp;lt;ref&amp;gt;López-de-Teruel P. E., García J. M., Acacio; The Parallel EM Algorithm and its Applications in Computer Vision&amp;lt;/ref&amp;gt;  авторы предлагают распределить вычисление скрытых переменных для каждого объекта между процессорами и на каждой итерации производить нормализацию. M-шаг предлагается параллелить по компонентам, что требует реализации корректного взаимодействия между процессорами. Предложенный вариант распараллеливания был реализован и протестирован авторами статьи с помощью MPI библиотеки MPICH. &lt;br /&gt;
&lt;br /&gt;
Авторы статьи &amp;lt;ref&amp;gt;Abhinandan Das, Mayur Datar, Ashutosh Garg; Google News Personalization: Scalable Online Collaborative Filtering&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&amp;lt;/ref&amp;gt; используют MapReduce для распараллеливания EM-алгоритма для PLSI моделей.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;/div&gt;</summary>
		<author><name>Algoman</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%9C%D0%B0%D1%80%D0%B8%D1%8F_%D0%93%D0%BE%D1%82%D0%BC%D0%B0%D0%BD&amp;diff=15102</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%9C%D0%B0%D1%80%D0%B8%D1%8F_%D0%93%D0%BE%D1%82%D0%BC%D0%B0%D0%BD&amp;diff=15102"/>
		<updated>2016-10-31T14:01:09Z</updated>

		<summary type="html">&lt;p&gt;Algoman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Замечания к [[Алгоритм_кластеризации,_основанный_на_максимизации_ожидания]] ==&lt;br /&gt;
&lt;br /&gt;
1) список литературы лучше оформить средствами разметки - см. как сделано в [[Разложение_Холецкого_(метод_квадратного_корня)]]&lt;br /&gt;
&lt;br /&gt;
Список литературы исправлен.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Замечения от 31.10 ==&lt;br /&gt;
&lt;br /&gt;
&amp;quot;- В конце статьи должен быть приведен список всех источников, откуда бралась информация по алгоритму. Если вы используется готовый рисунок, то сслыку на источник нужно разместить либо в подписи к рисунку, либо в тексте, где стоит ссылка на рисунок.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
какой источник картинок с графиками? созданы ли они авторами для этой статьи, публиковались ли где-то ещё?&lt;/div&gt;</summary>
		<author><name>Algoman</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:Sergey_Lavrushkin/EM-%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8&amp;diff=15098</id>
		<title>Участник:Sergey Lavrushkin/EM-алгоритм кластеризации</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:Sergey_Lavrushkin/EM-%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8&amp;diff=15098"/>
		<updated>2016-10-31T13:57:04Z</updated>

		<summary type="html">&lt;p&gt;Algoman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Algoman}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = EM-алгоритм кластеризации (1 итерация)&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(nkq^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(\log{n})&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(nk)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;nq + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;k(n + q^2 + q + 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
Автор статьи: [[Участник: Sergey Lavrushkin|Сергей Лаврушкин]] (группа 620)&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
==== EM-алгоритм ====&lt;br /&gt;
EM-алгоритм (англ. expectation-maximization) — алгоритм, используемый в математической статистике для нахождения оценок максимального правдоподобия параметров вероятностных моделей, в случае, когда модель зависит от некоторых скрытых переменных. Каждая итерация алгоритма состоит из двух шагов. На E-шаге (expectation) вычисляется ожидаемое значение функции правдоподобия, при этом скрытые переменные рассматриваются как наблюдаемые. На M-шаге (maximization) вычисляется оценка максимального правдоподобия, таким образом увеличивается ожидаемое правдоподобие, вычисляемое на E-шаге. Затем это значение используется для E-шага на следующей итерации. Алгоритм выполняется до сходимости.&amp;lt;ref&amp;gt;ЕМ-алгоритм, его модификации и обобщения [http://www.machinelearning.ru/wiki/index.php?title=EM-%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC http://www.machinelearning.ru/]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Как правило, ЕМ-алгоритм применяется для решения задач двух типов:&lt;br /&gt;
* К первому типу можно отнести задачи, связанные с анализом действительно неполных данных, когда некоторые статистические данные отсутствуют в силу каких-либо причин.&lt;br /&gt;
* Ко второму типу задач можно отнести те задачи, в которых функция правдоподобия имеет вид, не допускающий удобных аналитических методов исследования, но допускающий серьезные упрощения, если в задачу ввести дополнительные «ненаблюдаемые» (скрытые, латентные) переменные. Примерами прикладных задач второго типа являются задачи распознавания образов, реконструкции изображений. Математическую суть данных задач составляют задачи кластерного анализа, классификации и разделения смесей вероятностных распределений.&lt;br /&gt;
&lt;br /&gt;
Алгоритм основан на методике итеративного вычисления оценок максимального правдоподобия, предложенной в 1977 г. (A. P. Demster, N. M. Laird, D. B. Rubin. Maximum Likelihood from Incomplete Data via the EM Algorithm).&amp;lt;ref&amp;gt; A. Dempster, N. Laird and D. Rubin. Maximum likelihood estimation from incomplete data. – Journal of the Royal Statistical Society, Series B, 1977, vol. 39, p. 1-38.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Кластеризация с помощью EM-алгоритма ====&lt;br /&gt;
&lt;br /&gt;
Кластеризация — задача разбиения заданной выборки объектов (ситуаций) на непересекающиеся подмножества, называемые кластерами, так, чтобы каждый кластер состоял из схожих объектов, а объекты разных кластеров существенно отличались &amp;lt;ref&amp;gt;Кластеризация [http://www.machinelearning.ru/wiki/index.php?title=%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F www.machinelearning.ru]&amp;lt;/ref&amp;gt;. В основе идеи применения EM-алгоритма для кластеризации лежит предположение, что исследуемое множество данных может быть смоделировано с помощью линейной комбинации многомерных нормальных распределений, а целью является оценка параметров распределения, которые максимизируют логарифмическую функцию правдоподобия, используемую в качестве меры качества модели. К оцениваемым параметрам относятся математические ожидания и ковариационные матрицы. Предполагается, что любое наблюдение принадлежит ко всем кластерам, но с разной вероятностью. Задача заключается в &amp;quot;подгонке&amp;quot; распределений смеси к данным, а затем в определении вероятностей принадлежности наблюдения к каждому кластеру. Наблюдение должно быть отнесено к тому кластеру, для которого данная вероятность выше.&lt;br /&gt;
&lt;br /&gt;
Алгоритм EM основан на вычислении расстояний. Он может рассматриваться как обобщение кластеризации на основе анализа смеси вероятностных распределений. В процессе работы алгоритма происходит итеративное улучшение решения, а остановка осуществляется в момент, когда достигается требуемый уровень точности модели. Мерой в данном случае является монотонно увеличивающаяся статистическая величина, называемая логарифмическим правдоподобием.&amp;lt;ref&amp;gt;EМ — масштабируемый алгоритм кластеризации [https://basegroup.ru/community/articles/em basegroup.ru]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
Исходные данные: &lt;br /&gt;
* &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; — число кластеров,&lt;br /&gt;
* &amp;lt;math&amp;gt;X =\{x_{1}, x_{2}, ..., x_{n}\}&amp;lt;/math&amp;gt; — множество из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; наблюдений &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt;-мерного пространства.&lt;br /&gt;
Вычисляемые данные:&lt;br /&gt;
* &amp;lt;math&amp;gt;(w, \theta) = (w_1, ..., w_k; \mu_1, ..., \mu_k; \Sigma_1, ..., \Sigma_k)&amp;lt;/math&amp;gt; — параметры смеси гауссовых распределений,&lt;br /&gt;
* &amp;lt;math&amp;gt;Y&amp;lt;/math&amp;gt; — матрица размера &amp;lt;math&amp;gt;n \times k&amp;lt;/math&amp;gt; с вероятностями членства в кластерах.&lt;br /&gt;
==== Постановка задачи разделения смеси гауссовых распределений ====&lt;br /&gt;
Пусть &amp;lt;math&amp;gt;w_1, ..., w_k&amp;lt;/math&amp;gt; — априорные вероятности кластеров, &amp;lt;math&amp;gt;p_1(x), ..., p_k(x)&amp;lt;/math&amp;gt; — плотности распределения кластеров.&lt;br /&gt;
Тогда плотность распределения вектора признаков &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; сразу по всем кластерам равна:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
p(x) = \sum_{j=1}^{k}w_jp_j(x)&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Необходимо на основе выборки оценить параметры модели &amp;lt;math&amp;gt;w_1, ..., w_k, p_1(x), ..., p_k(x)&amp;lt;/math&amp;gt;. Это позволит оценивать вероятность принадлежности к кластеру и, таким образом, решить задачу кластеризации. Такая задача&lt;br /&gt;
называется задачей разделения смеси распределений:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
p(x) = \sum_{j=1}^{k}w_jp_j(x),\quad p_j(x) = \phi(\theta_j; x),&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где &amp;lt;math&amp;gt;\theta_j&amp;lt;/math&amp;gt; — параметры распределения &amp;lt;math&amp;gt;p_j(x)&amp;lt;/math&amp;gt;.&lt;br /&gt;
В случае смести гауссовых распределений предполагается, что все компоненты имеют многомерное нормальное распределение. То есть в случае &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt;-мерного пространства признаков &amp;lt;math&amp;gt;\phi(\theta_j; x)&amp;lt;/math&amp;gt; имеют следующий вид:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
&amp;amp; \phi(\theta_j; x) = \frac{1}{\Big(2\pi\Big)^{\frac{q}{2}}\sqrt{|\Sigma_j|}}\exp{\bigg\{-\frac{\delta^2}{2}\bigg\} },\\ &lt;br /&gt;
&amp;amp; \delta^2 = \Big( x - \mu_j \Big)^T \Sigma_j^{-1} \Big( x - \mu_j \Big),&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
где:&lt;br /&gt;
* &amp;lt;math&amp;gt;\Sigma_j&amp;lt;/math&amp;gt; — ковариационная матрица размером &amp;lt;math&amp;gt;q \times q&amp;lt;/math&amp;gt;,&lt;br /&gt;
* &amp;lt;math&amp;gt;\mu_j&amp;lt;/math&amp;gt; — &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt;-мерный вектор математических ожиданий,&lt;br /&gt;
* &amp;lt;math&amp;gt;\delta^2&amp;lt;/math&amp;gt; — квадратичное расстояние Махаланобиса.&lt;br /&gt;
В случае смеси гауссовых распределений получаем, что &amp;lt;math&amp;gt;\theta_j = (\mu_j, \Sigma_j)&amp;lt;/math&amp;gt;. То есть для решения задачи разделения смеси гауссовых распределений необходимо оценить вектор параметров &amp;lt;math&amp;gt;(w, \theta) = (w_1, ..., w_k; \mu_1, ..., \mu_k; \Sigma_1, ..., \Sigma_k)&amp;lt;/math&amp;gt;. Согласно принципу максимизации правдоподобия:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
w, \theta = \underset{w, \theta}{\operatorname{argmax}} \sum_{i=1}^{n}\ln{p(x_i)} = \underset{w, \theta}{\operatorname{argmax}} \sum_{i=1}^{n}\ln{\sum_{j=1}^{k}w_jp_j(x_i)}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Таким образом, имеет место задача максимизации суммы логарифмов сумм, решение которой представляет большую трудность. В таком случае полезным оказывается итеративный метод решения — EM-алгоритм.&amp;lt;ref&amp;gt;Поиск структуры в данных — Lecture 9 — Expectation Maximization (EM-алгоритм) [https://www.coursera.org/learn/unsupervised-learning/lecture/2jhbI/expectation-maximization-em-alghoritm www.coursera.org]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== EM-алгоритм ====&lt;br /&gt;
Оптимальные параметры задачи разделения смеси гауссовых распределений отыскиваются последовательно с помощью итерационного EM-алгоритма. Основная идея – вводится вспомогательный вектор скрытых переменных. Это позволяет свести сложную оптимизационную задачу к последовательности итераций по пересчету коэффициентов (скрытых переменных по текущему приближению вектора параметров - E-шаг) и максимизации правдоподобия (с целью найти следующее приближение вектора - М-шаг).&amp;lt;ref&amp;gt;EM алгоритм (пример) [http://www.machinelearning.ru/wiki/index.php?title=EM_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_(%D0%BF%D1%80%D0%B8%D0%BC%D0%B5%D1%80) www.machinelearning.ru]&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
EM-алгоритм заключается в следующем:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; В начале работы алгоритма задаются параметры начального приближения. Наиболее общим способом инициализации является присвоение элементам матрицы математических ожиданий случайных значений &amp;lt;math&amp;gt; \mu_j \leftarrow Random &amp;lt;/math&amp;gt;, начальные ковариационные матрицы определяются как единчиные &amp;lt;math&amp;gt;\Sigma_j \leftarrow I&amp;lt;/math&amp;gt;, веса кластеров задаются одинаковыми &amp;lt;math&amp;gt;w_i \leftarrow \frac{1}{k}&amp;lt;/math&amp;gt;. Также в качестве начальных параметров можно использовать результат работы алгоритма K-means. (Данная эвристика применяется, так как K-means требуется намного меньше итераций до достижения стабилизации, в то время как каждый шаг EM требует больших вычислительных затрат).&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; Далее итеративно выполняется следующая пара процедур:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;E-шаг: используя текущее значение вектора параметров &amp;lt;math&amp;gt;(w, \theta) = (w_1, ..., w_k; \mu_1, ..., \mu_k; \Sigma_1, ..., \Sigma_k)&amp;lt;/math&amp;gt;, вычисляем значения скрытых переменных &amp;lt;math&amp;gt;y_{ij}&amp;lt;/math&amp;gt;:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
&amp;amp; y_{ij} = \frac{w_j p_j(x_i)}{\sum_{l=1}^{k}w_lp_l(x_i)}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;М-шаг: переоценка вектора параметров, используя текущие значения скрытых переменных:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
&amp;amp; n_j = \sum_{i = 1}^{n}y_{ij}, \\&lt;br /&gt;
&amp;amp; \mu_j^{new} = \frac{1}{n_j} \sum_{i = 1}^{n}y_{ij}x_i, \\&lt;br /&gt;
&amp;amp; \Sigma_j^{new} = \frac{1}{n_j} \sum_{i = 1}^{n}y_{ij}(x_i - \mu_j^{new})(x_i - \mu_j^{new})^T,\\&lt;br /&gt;
&amp;amp; w_j^{new} = \frac{n_j}{n}.&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
Итерации происходят до сходимости (норма разности векторов скрытых переменных или изменение логарифмического правдоподобия на каждой итерации не будет превышать заданную константу) или достижения максимального числа итераций.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
В вычислительное ядро EM-алгоритма входят:&lt;br /&gt;
* Вычисление скрытых переменных &amp;lt;math&amp;gt;y_{ij}&amp;lt;/math&amp;gt; на E-шаге (всего их &amp;lt;math&amp;gt;nk&amp;lt;/math&amp;gt;).&lt;br /&gt;
* Переоценка вектора параметров &amp;lt;math&amp;gt;(w_1, ..., w_k; \mu_1, ..., \mu_k; \Sigma_1, ..., \Sigma_k)&amp;lt;/math&amp;gt; на M-шаге, используя текущие значения скрытых переменных &amp;lt;math&amp;gt;y_{ij}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Как записано в описании ядра алгоритма, основную часть метода составляют множественные вычисления скрытых переменных &amp;lt;math&amp;gt;y_{ij}&amp;lt;/math&amp;gt; на E-шаге и обновление вектора параметров &amp;lt;math&amp;gt;(w_1, ..., w_k; \mu_1, ..., \mu_k; \Sigma_1, ..., \Sigma_k)&amp;lt;/math&amp;gt; на M-шаге.&lt;br /&gt;
Также стоит выделить вычисление определителя и обратной матрицы ковариационных матриц &amp;lt;math&amp;gt;\Sigma_j&amp;lt;/math&amp;gt; в начале E-шага.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
Последовательная реализация алгоритма EM может быть проиллюстрирована с помощью следующего псевдокода:&lt;br /&gt;
# &#039;&#039;&#039;Инициализация&#039;&#039;&#039;: установка начальных значений &amp;lt;math&amp;gt;\mu, \, \Sigma_j \, (j = \overline{1, k}), \, w&amp;lt;/math&amp;gt;.&lt;br /&gt;
# &#039;&#039;&#039;Пока&#039;&#039;&#039; изменение логарифмического правдоподобия &amp;lt;math&amp;gt;\Delta llh \geq \epsilon&amp;lt;/math&amp;gt; и не достигнуто максимальное число итераций &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, &#039;&#039;&#039;выполнять&#039;&#039;&#039; шаги E и M.&lt;br /&gt;
&#039;&#039;&#039;Шаг E&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;def&#039;&#039;&#039; E-step:&lt;br /&gt;
     &#039;&#039;&#039;Инициализировать&#039;&#039;&#039; нулевыми значениями &amp;lt;math&amp;gt;\mu^{&#039;}, \, \Sigma_j^{&#039;} \, (j = \overline{1, k}), \, w^{&#039;}, \, llh&amp;lt;/math&amp;gt;&lt;br /&gt;
     &#039;&#039;&#039;for&#039;&#039;&#039; &amp;lt;math&amp;gt;j = \overline{1, k}&amp;lt;/math&amp;gt;:&lt;br /&gt;
         &#039;&#039;&#039;Вычислить&#039;&#039;&#039; определитель и обратную матрицу матрицы &amp;lt;math&amp;gt;\Sigma_j&amp;lt;/math&amp;gt;&lt;br /&gt;
     &#039;&#039;&#039;for&#039;&#039;&#039; &amp;lt;math&amp;gt;i = \overline{1, n}&amp;lt;/math&amp;gt;:&lt;br /&gt;
         &amp;lt;math&amp;gt;sump_i = 0&amp;lt;/math&amp;gt;&lt;br /&gt;
         &#039;&#039;&#039;for&#039;&#039;&#039; &amp;lt;math&amp;gt;j = \overline{1, k}&amp;lt;/math&amp;gt;:&lt;br /&gt;
             &amp;lt;math&amp;gt;\delta_{ij} = \big( x_i - \mu_j \big)^T \Sigma_j^{-1} \big( x_i - \mu_j \big)&amp;lt;/math&amp;gt;&lt;br /&gt;
             &amp;lt;math&amp;gt;g_{ij} = \frac{w_j}{{2 \pi}^\frac{q}{2}|\Sigma_j|}\exp{\big\{-\frac{\delta^2}{2}\big\} }&amp;lt;/math&amp;gt;&lt;br /&gt;
             &amp;lt;math&amp;gt;sump_i \mathrel{+}= g_{ij}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;y_i = \frac{g_i}{sump_i}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;llh \mathrel{+}= \ln(sump_i)&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\mu^{&#039;} \mathrel{+}= x_iy_i^T&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;w^{&#039;} \mathrel{+}= y_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Шаг M&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;def&#039;&#039;&#039; M-step:&lt;br /&gt;
     &#039;&#039;&#039;for&#039;&#039;&#039; &amp;lt;math&amp;gt;j = \overline{1, k}&amp;lt;/math&amp;gt;:&lt;br /&gt;
         &amp;lt;math&amp;gt;\mu_j = \frac{\mu_j^{&#039;}}{w_j^{&#039;}}&amp;lt;/math&amp;gt;&lt;br /&gt;
         &#039;&#039;&#039;for&#039;&#039;&#039; &amp;lt;math&amp;gt;i = \overline{1, n}&amp;lt;/math&amp;gt;:&lt;br /&gt;
             &amp;lt;math&amp;gt;\Sigma_j^{&#039;} \mathrel{+}= (x_i - \mu_j)y_{ij}(x_i - \mu_j)^T&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;\Sigma_j = \frac{\Sigma_j^{&#039;}}{w_j^{&#039;}}&amp;lt;/math&amp;gt;&lt;br /&gt;
     &amp;lt;math&amp;gt;w = \frac{w^{&#039;}}{n}&amp;lt;/math&amp;gt;&lt;br /&gt;
Логаририфмическое правдоподобие вычисляется как:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
llh=\sum_{i=1}^{n}\ln{(sump_i)}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Матрицы &amp;lt;math&amp;gt;\mu^{&#039;}, \, \Sigma_j^{&#039;} \, (j = \overline{1, k}), \, w^{&#039;}&amp;lt;/math&amp;gt; являются временными и используются только для вычислений.&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
Последовательная сложность одной итерации EM-алгоритма:&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; E-шаг: &amp;lt;br&amp;gt;&lt;br /&gt;
В случае недиагональных ковариационных матриц сложность вычислений:&lt;br /&gt;
* Определителей ковариационных матриц &amp;lt;math&amp;gt;|\Sigma_j|&amp;lt;/math&amp;gt; (&amp;lt;math&amp;gt;j = \overline{1, k}&amp;lt;/math&amp;gt;) методом Гаусса: &amp;lt;math&amp;gt;O(kq^3)&amp;lt;/math&amp;gt;,&lt;br /&gt;
* Матриц, обратных ковариационным матрицам &amp;lt;math&amp;gt;\Sigma_j^{-1}&amp;lt;/math&amp;gt; (&amp;lt;math&amp;gt;j = \overline{1, k}&amp;lt;/math&amp;gt;) методом Гаусса-Жордана: &amp;lt;math&amp;gt;O(kq^3)&amp;lt;/math&amp;gt;,&lt;br /&gt;
* Скрытых переменных &amp;lt;math&amp;gt;y_{ij}&amp;lt;/math&amp;gt; (&amp;lt;math&amp;gt;i = \overline{1, n}, j = \overline{1, k}&amp;lt;/math&amp;gt;): &amp;lt;math&amp;gt;O(nkq^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
В случае диагональных ковариационных матриц сложность вычислений:&lt;br /&gt;
* Определителей ковариационных матриц &amp;lt;math&amp;gt;|\Sigma_j|&amp;lt;/math&amp;gt; (&amp;lt;math&amp;gt;j = \overline{1, k}&amp;lt;/math&amp;gt;): &amp;lt;math&amp;gt;O(kq)&amp;lt;/math&amp;gt;,&lt;br /&gt;
* Матриц, обратных ковариационным матрицам &amp;lt;math&amp;gt;\Sigma_j^{-1}&amp;lt;/math&amp;gt; (&amp;lt;math&amp;gt;j = \overline{1, k}&amp;lt;/math&amp;gt;): &amp;lt;math&amp;gt;O(kq)&amp;lt;/math&amp;gt;,&lt;br /&gt;
* Скрытых переменных &amp;lt;math&amp;gt;y_{ij}&amp;lt;/math&amp;gt; (&amp;lt;math&amp;gt;i = \overline{1, n}, j = \overline{1, k}&amp;lt;/math&amp;gt;): &amp;lt;math&amp;gt;O(nkq)&amp;lt;/math&amp;gt;.&lt;br /&gt;
Получаем, что последовательная сложность E-шага в случае недиагональных ковариационных матриц имеет порядок &amp;lt;math&amp;gt;O(kq^3 + nkq^2)&amp;lt;/math&amp;gt;, а в случае диагональных ковариационных матриц — &amp;lt;math&amp;gt;O(nkq)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&lt;br /&gt;
М-шаг: &amp;lt;br&amp;gt;&lt;br /&gt;
В случае недиагональных ковариационных матриц сложность вычислений:&lt;br /&gt;
* Обновление математических ожиданий &amp;lt;math&amp;gt;\mu_j&amp;lt;/math&amp;gt; (&amp;lt;math&amp;gt;j = \overline{1, k}&amp;lt;/math&amp;gt;): &amp;lt;math&amp;gt;O(nkq)&amp;lt;/math&amp;gt;,&lt;br /&gt;
* Обновление ковариационных матриц &amp;lt;math&amp;gt;\Sigma_j&amp;lt;/math&amp;gt; (&amp;lt;math&amp;gt;j = \overline{1, k}&amp;lt;/math&amp;gt;): &amp;lt;math&amp;gt;O(nkq^2)&amp;lt;/math&amp;gt;,&lt;br /&gt;
* Обновление весов кластеров &amp;lt;math&amp;gt;w_j&amp;lt;/math&amp;gt; (&amp;lt;math&amp;gt;j = \overline{1, k}&amp;lt;/math&amp;gt;): &amp;lt;math&amp;gt;O(nk)&amp;lt;/math&amp;gt;.&lt;br /&gt;
В случае диагональных ковариационных матриц сложность вычислений:&lt;br /&gt;
* Обновление математических ожиданий &amp;lt;math&amp;gt;\mu_j&amp;lt;/math&amp;gt; (&amp;lt;math&amp;gt;j = \overline{1, k}&amp;lt;/math&amp;gt;): &amp;lt;math&amp;gt;O(nkq)&amp;lt;/math&amp;gt;,&lt;br /&gt;
* Обновление ковариационных матриц &amp;lt;math&amp;gt;\Sigma_j&amp;lt;/math&amp;gt; (&amp;lt;math&amp;gt;j = \overline{1, k}&amp;lt;/math&amp;gt;): &amp;lt;math&amp;gt;O(nkq)&amp;lt;/math&amp;gt;,&lt;br /&gt;
* Обновление весов кластеров &amp;lt;math&amp;gt;w_j&amp;lt;/math&amp;gt; (&amp;lt;math&amp;gt;j = \overline{1, k}&amp;lt;/math&amp;gt;): &amp;lt;math&amp;gt;O(nk)&amp;lt;/math&amp;gt;.&lt;br /&gt;
Получаем, что последовательная сложность М-шага в случае недиагональных ковариационных матриц имеет порядок &amp;lt;math&amp;gt;O(nkq^2)&amp;lt;/math&amp;gt;, а в случае диагональных ковариационных матриц — &amp;lt;math&amp;gt;O(nkq)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
Таким образом, последовательная сложность итерации EM-алгоритма в случае недиагональных ковариационных матриц имеет порядок &amp;lt;math&amp;gt;O(kq^3 + nkq^2)&amp;lt;/math&amp;gt;, а в случае диагональных ковариационных матриц — &amp;lt;math&amp;gt;O(nkq)&amp;lt;/math&amp;gt;. При этом, обычно размерность элементов выборки &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt;, также как и число кластеров &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;, значительно меньше числа элементов выборки &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; (&amp;lt;math&amp;gt;k \ll n, q \ll n&amp;lt;/math&amp;gt;), поэтому в случае недиагональных ковариационных матриц сложность может быть записана в виде &amp;lt;math&amp;gt;O(nkq^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
&lt;br /&gt;
Граф алгоритма в терминах E-шагов и M-шагов представлен на рис. 1. Каждая итерация алгоритма зависит от результата работы предыдущей итерации, M-шаг зависит от результата E-шага.&lt;br /&gt;
&lt;br /&gt;
[[Файл:EM-alg-Lavrushkin.png|thumb|1000px|center|Рисунок 1. Граф EM-алгоритма. &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; — число кластеров; &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; — множество наблюдений; &amp;lt;math&amp;gt;Y&amp;lt;/math&amp;gt; — матрица с вероятностями членства в кластерах.]]&lt;br /&gt;
&lt;br /&gt;
Рассмотрим по отдельности информационные графы E-шага и M-шага.&lt;br /&gt;
&lt;br /&gt;
==== E-шаг ====&lt;br /&gt;
Опишем граф E-шага как аналитически, так и в виде рисунка.&lt;br /&gt;
&lt;br /&gt;
Граф алгоритма состоит из четырех групп вершин:&lt;br /&gt;
*&#039;&#039;&#039;Первая&#039;&#039;&#039; группа вершин соответствует вычислению обратных матриц и определителей ковариационных матриц. Число вершин: &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;. Аргументом этой операции является ковариационная матрица &amp;lt;math&amp;gt;\Sigma_j&amp;lt;/math&amp;gt;. Результат срабатывания операции является промежуточным данным алгоритма.&lt;br /&gt;
*&#039;&#039;&#039;Вторая&#039;&#039;&#039; группа вершин соответствует вычислению &amp;lt;math&amp;gt;g_{ij} = \frac{w_j}{{2 \pi}^\frac{q}{2}|\Sigma_j|}\exp{\big\{-\frac{1}{2}  \big( x_i - \mu_j \big)^T \Sigma_j^{-1} \big( x_i - \mu_j \big)  \big\}}&amp;lt;/math&amp;gt;. Число вершин: &amp;lt;math&amp;gt;nk&amp;lt;/math&amp;gt;. Аргументами этой операции являются вес кластера &amp;lt;math&amp;gt;w_j&amp;lt;/math&amp;gt;, математическое ожидание &amp;lt;math&amp;gt;\mu_j&amp;lt;/math&amp;gt;, ковариационная матрица &amp;lt;math&amp;gt;\Sigma_j&amp;lt;/math&amp;gt;, элемент выборки &amp;lt;math&amp;gt;x_i&amp;lt;/math&amp;gt;. Результат срабатывания операции является промежуточным данным алгоритма.&lt;br /&gt;
*&#039;&#039;&#039;Третья&#039;&#039;&#039; группа вершин соответствует вычислению нормировочных коэффициентов &amp;lt;math&amp;gt;\sum_{l=1}^{k}g_{ij}&amp;lt;/math&amp;gt;. Число вершин: &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;. Аргументами этой операции являются значения &amp;lt;math&amp;gt;g_{ij}, \, j = \overline{1, k}&amp;lt;/math&amp;gt;. Результат срабатывания операции является промежуточным данным алгоритма.&lt;br /&gt;
*&#039;&#039;&#039;Четвертая&#039;&#039;&#039; группа вершин соответствует вычислению скрытых переменных &amp;lt;math&amp;gt;y_{ij}&amp;lt;/math&amp;gt;. Число вершин: &amp;lt;math&amp;gt;nk&amp;lt;/math&amp;gt;. Аргументами этой операции являются значение &amp;lt;math&amp;gt;g_{ij}&amp;lt;/math&amp;gt; и нормировочный коэффициент. Результат срабатывания операции является выходным данным алгоритма.&lt;br /&gt;
&lt;br /&gt;
Описанный граф представлен на рис.2 и рис.3. Здесь вершины одной группы расположены в одной строке. Вершины-операции обозначены синим цветом, вершины-данные — оранжевым.&lt;br /&gt;
&lt;br /&gt;
[[Файл:E-step-Lavrushkin.png|thumb|1000px|center|Рисунок 2. Граф E-шага.]]&lt;br /&gt;
[[Файл:E-step2-Lavrushkin.png|thumb|800px|center|Рисунок 3. Граф E-шага с с отображением входных и выходных данных.]]&lt;br /&gt;
&lt;br /&gt;
==== M-шаг ====&lt;br /&gt;
Опишем граф M-шага как аналитически, так и в виде рисунка.&lt;br /&gt;
&lt;br /&gt;
Граф алгоритма состоит из четырех групп вершин:&lt;br /&gt;
*&#039;&#039;&#039;Первая&#039;&#039;&#039; группа вершин соответствует вычислению нормировочных коэффициентов &amp;lt;math&amp;gt;n_j&amp;lt;/math&amp;gt;. Число вершин: &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;. Аргументами этой операции являются скрытые переменные &amp;lt;math&amp;gt;y_{ij}, \, i = \overline{1, n}&amp;lt;/math&amp;gt;. Результат срабатывания операции является промежуточным данным алгоритма.&lt;br /&gt;
*&#039;&#039;&#039;Вторая&#039;&#039;&#039; группа вершин соответствует вычислению математических ожиданий &amp;lt;math&amp;gt;\mu_j&amp;lt;/math&amp;gt;. Число вершин: &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;. Аргументами этой операции являются множество наблюдений &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt;, скрытые переменные &amp;lt;math&amp;gt;y_{ij}, \, i = \overline{1, n}&amp;lt;/math&amp;gt;, нормировочный коэффициент &amp;lt;math&amp;gt;n_j&amp;lt;/math&amp;gt;. Результат срабатывания операции является выходным данным алгоритма.&lt;br /&gt;
*&#039;&#039;&#039;Третья&#039;&#039;&#039; группа вершин соответствует вычислению ковариационных матриц &amp;lt;math&amp;gt;\Sigma_j&amp;lt;/math&amp;gt;. Число вершин: &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;. Аргументами этой операции являются множество наблюдений &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt;, скрытые переменные &amp;lt;math&amp;gt;y_{ij}, \, i = \overline{1, n}&amp;lt;/math&amp;gt;, нормировочный коэффициент &amp;lt;math&amp;gt;n_j&amp;lt;/math&amp;gt;, математическое ожидание &amp;lt;math&amp;gt;\mu_j&amp;lt;/math&amp;gt;. Результат срабатывания операции является выходным данным алгоритма.&lt;br /&gt;
*&#039;&#039;&#039;Четвертая&#039;&#039;&#039; группа вершин соответствует вычислению весов кластеров &amp;lt;math&amp;gt;w_{j}&amp;lt;/math&amp;gt;. Число вершин: &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;. Аргументом этой операции является нормировочный коэффициент &amp;lt;math&amp;gt;n_j&amp;lt;/math&amp;gt;. Результат срабатывания операции является выходным данным алгоритма.&lt;br /&gt;
&lt;br /&gt;
Описанный граф представлен на рис.4 и рис.5. Здесь вершины одной группы расположены в одной строке. Вершины-операции обозначены синим цветом, вершины-данные — оранжевым.&lt;br /&gt;
&lt;br /&gt;
[[Файл:M-step-Lavrushkin.png|thumb|1000px|center|Рисунок 4. Граф M-шага.]]&lt;br /&gt;
[[Файл:M-step2-Lavrushkin.png|thumb|600px|center|Рисунок 5. Граф M-шага с отображением входных и выходных данных.]]&lt;br /&gt;
&lt;br /&gt;
Графы вычисления математических ожиданий &amp;lt;math&amp;gt;\mu_j&amp;lt;/math&amp;gt; и ковариационных матриц &amp;lt;math&amp;gt;\Sigma_j&amp;lt;/math&amp;gt; представлены на рис. 6 и рис. 7.&lt;br /&gt;
&lt;br /&gt;
[[Файл:EM-alg-mean-Lavrushkin.png|thumb|1400px|center|Рисунок 6. Граф вычисления математического ожидания &amp;lt;math&amp;gt;\mu_j&amp;lt;/math&amp;gt;.]]&lt;br /&gt;
[[Файл:EM-alg-cov-Lavrushkin.png|thumb|1400px|center|Рисунок 7. Граф вычисления ковариационной матрицы &amp;lt;math&amp;gt;\Sigma_j&amp;lt;/math&amp;gt;.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
По графам из пункта 1.7 видно, что скрытые переменные &amp;lt;math&amp;gt;y_{ij}&amp;lt;/math&amp;gt; в E-шаге, &amp;lt;math&amp;gt;y_{ij}x_i&amp;lt;/math&amp;gt; в вычислении математических ожиданий &amp;lt;math&amp;gt;\mu_{j}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;y_{ij}(x_i - \mu_j)(x_i - \mu_j)&amp;lt;/math&amp;gt; в вычислении ковариационных матриц &amp;lt;math&amp;gt;\Sigma_{j}&amp;lt;/math&amp;gt; в M-шаге вычисляются независимо (&amp;lt;math&amp;gt;i = \overline{1, n}, \, j = \overline{1, k}&amp;lt;/math&amp;gt;). Таким образом, при условии наличия неограниченного числа процессоров эти операции можно распараллелить как по числу наблюдений, так и по числу кластеров. Однако в отсутствии неограниченного числа процессорв целесообразно проводить распараллеливание по числу наблюдений, потому что, как правило, число наблюдений значительно больше числа кластеров  (&amp;lt;math&amp;gt;n \gg q&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
При классификации по ширине ЯПФ его сложность будет &amp;lt;math&amp;gt;O(nk)&amp;lt;/math&amp;gt;. Сложность ЯПФ при классификации по высоте зависит от способа вычисления обратных матриц и определителей ковариационных матриц, а также от способа суммирования при вычислении скрытых переменных и обновлении вектора параметров. Предположим, что размерность элементов выборки &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; и число кластеров &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; значительно меньше числа элементов выборки &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; (&amp;lt;math&amp;gt;k \ll n, q \ll n&amp;lt;/math&amp;gt;). Тогда вычисление обратных матриц и определителей ковариационных матриц можно не учитывать, также как и суммирование при вычислении скрытых переменных. Пусть для вычисления сумм при обновлении вектора параметров используется пирамида сдваиванием. Тогда их сложность будет равна &amp;lt;math&amp;gt;O(\log{n})&amp;lt;/math&amp;gt;. Следовательно, при классификации по высоте ЯПФ его сложность будет &amp;lt;math&amp;gt;O(\log{n})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; — число кластеров; &amp;lt;math&amp;gt;X =\{x_{1}, x_{2}, ..., x_{n}\}&amp;lt;/math&amp;gt; — множество из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; наблюдений &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt;-мерного пространства.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем входных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;nq + 1&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: &amp;lt;math&amp;gt;(w, \theta) = (w_1, ..., w_k; \mu_1, ..., \mu_k; \Sigma_1, ..., \Sigma_k)&amp;lt;/math&amp;gt; — параметры смеси гауссовых распределений; &amp;lt;math&amp;gt;Y&amp;lt;/math&amp;gt; — матрица размера &amp;lt;math&amp;gt;n \times k&amp;lt;/math&amp;gt; с вероятностями членства в кластерах.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объем выходных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;k(n + q^2 + q + 1)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
Алгоритм является &#039;&#039;недетерминированным&#039;&#039;. Число итераций до сходимости метода зависит от начального приближения и выбранного критерия останова.&lt;br /&gt;
&lt;br /&gt;
Предположим, что размерность элементов выборки &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; и число кластеров &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; значительно меньше числа элементов выборки &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; (&amp;lt;math&amp;gt;k \ll n, q \ll n&amp;lt;/math&amp;gt;), а число итераций до сходимости метода равно &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;. Тогда вычислительная мощность алгоритма, как отношение числа операций к суммарному объему входных и выходных данных, имеет порядок &amp;lt;math&amp;gt;O\bigg(\frac{kq^2}{q + k}m\bigg)&amp;lt;/math&amp;gt;.&lt;br /&gt;
==== Достоинства и недостатки алгоритма ====&lt;br /&gt;
Среди достоинств EM-алгоритма можно выделить следующие:&lt;br /&gt;
* Мощная статистическая основа.&lt;br /&gt;
* Линейное увеличение сложности при росте объема данных.&lt;br /&gt;
* Устойчивость к шумам и пропускам в данных.&lt;br /&gt;
* Возможность построения желаемого числа кластеров.&lt;br /&gt;
* Быстрая сходимость при удачной инициализации.&lt;br /&gt;
К недостаткам EM-алгоритма можно отнести следующее:&lt;br /&gt;
* Алгоритм неустойчив по начальным данным (то есть тем, которые инициализируют вектор параметров на первой итерации), так как он находит локальный экстремум, значение которого может оказаться гораздо ниже, чем глобальный максимум. В зависимости от выбора начального приближения алгоритм может сходиться к разным точкам. Также может сильно варьироваться скорость сходимости.&lt;br /&gt;
* Алгоритм не позволяет определять количество &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; компонент смеси. Эта величина является структурным параметром алгоритма.&lt;br /&gt;
* Предположение о нормальности всех измерений данных не всегда выполняется.&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
&lt;br /&gt;
==== Масштабируемость алгоритма ====&lt;br /&gt;
&lt;br /&gt;
==== Масштабируемость реализации алгоритма ====&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
# [http://docs.opencv.org/2.4/modules/ml/doc/expectation_maximization.html OpenCV];&lt;br /&gt;
# [http://arma.sourceforge.net/docs.html#gmm_diag Armadillo] — OpenMP реализация с предположением диагональности ковариационных матриц;&lt;br /&gt;
# [http://www.mlpack.org/docs/mlpack-git/doxygen.php?doc=classmlpack_1_1gmm_1_1GMM.html MLPack];&lt;br /&gt;
# [http://scikit-learn.org/stable/modules/mixture.html scikit-learn];&lt;br /&gt;
# [http://www.mathworks.com/help/stats/clustering-using-gaussian-mixture-models.html Matlab];&lt;br /&gt;
# [https://github.com/Corv/CUDA-GMM-MultiGPU CUDA реализация №1];&lt;br /&gt;
# [http://andrewharp.com/gmmcuda CUDA реализация №2].&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;/div&gt;</summary>
		<author><name>Algoman</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%90%D0%BB%D0%B5%D0%BA%D1%81%D0%B0%D0%BD%D0%B4%D1%80_%D0%9A%D1%83%D0%B2%D0%B0%D0%B5%D0%B2/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8,_%D0%BE%D1%81%D0%BD%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9_%D0%BD%D0%B0_%D0%BC%D0%B0%D0%BA%D1%81%D0%B8%D0%BC%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BE%D0%B6%D0%B8%D0%B4%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=15095</id>
		<title>Участник:Александр Куваев/Алгоритм кластеризации, основанный на максимизации ожидания</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%90%D0%BB%D0%B5%D0%BA%D1%81%D0%B0%D0%BD%D0%B4%D1%80_%D0%9A%D1%83%D0%B2%D0%B0%D0%B5%D0%B2/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8,_%D0%BE%D1%81%D0%BD%D0%BE%D0%B2%D0%B0%D0%BD%D0%BD%D1%8B%D0%B9_%D0%BD%D0%B0_%D0%BC%D0%B0%D0%BA%D1%81%D0%B8%D0%BC%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BE%D0%B6%D0%B8%D0%B4%D0%B0%D0%BD%D0%B8%D1%8F&amp;diff=15095"/>
		<updated>2016-10-31T13:54:49Z</updated>

		<summary type="html">&lt;p&gt;Algoman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Авторы описания:&lt;br /&gt;
* Куваев А.С., группа 620 (математическая постановка задачи, схема реализации алгоритма, оценка сложности, описание ресурса параллелизма)&lt;br /&gt;
* Щенявская Е.В., группа 616 (описание алгоритма, визуализация информационного графа и примера работы алгоритма, описание свойств алгоритма)&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритмов ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
Задача кластеризации заключается в разбиении входного множества объектов на непересекающиеся подмножества, называемые кластерами, так, чтобы каждый кластер состоял из схожих объектов, а объекты разных кластеров существенно отличались друг от друга&amp;lt;ref name=vorontsov&amp;gt;Воронцов К.В., Математические методы обучения по прецедентам.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Решение этой задачи принципиально неоднозначно по следующим причинам&amp;lt;ref name=vorontsov/&amp;gt;:&lt;br /&gt;
# результат кластеризации зависит от способа задания меры сходства объектов выборки&lt;br /&gt;
# не существует однозначно наилучшего критерия качества кластеризации&lt;br /&gt;
# число кластеров, как правило, неизвестно заранее и задается из некоторых априорных соображений (хотя существуют алгоритмы, способные определять число кластеров автоматически)&lt;br /&gt;
&lt;br /&gt;
По описанной выше причине существует большое число алгоритмов кластеризации, приводящих к различным разбиениям исходного множества объектов. На этой странице представлено описание одного из таких методов — EM-алгоритма. EM-алгоритм опирается на предположение о вероятностной природе данных: элементы выборки получены случайно и независимо из смеси распределений с фиксированным числом компонент &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;. Таким образом, плотность распределения на множестве объектов имеет следующий вид:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;p(x)=\sum_{j=1}^{k}w_{j}p_{j}(x), \ \sum_{j=1}^{k}w_{j}=1, \ w_{j} \ge 0 &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;p_{j}&amp;lt;/math&amp;gt; - плотность распределения &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-й компоненты смеси (кластера).&lt;br /&gt;
&lt;br /&gt;
Везде в дальнейшем будем предполагать, что &amp;lt;math&amp;gt;p_{j}&amp;lt;/math&amp;gt; имеют вид многомерных нормальных плотностей с произвольной матрицей ковариации: смеси нормальных распределений позволяют аппроксимировать произвольные непрерывные функции плотности с наперед заданной точностью&amp;lt;ref name=korolev&amp;gt;Королёв В.Ю., ЕМ-алгоритм, его модификации и их применение к задаче разделения смесей вероятностных распределений. Теоретический обзор. - М.: ИПИРАН, 2007.&amp;lt;/ref&amp;gt;. Результатом работы EM-алгоритма являются оценки априорных вероятностей компонент смеси &amp;lt;math&amp;gt;w_{j}&amp;lt;/math&amp;gt;, а также оценки векторов математических ожиданий и матриц ковариаций для каждой компоненты. Зная параметры распределения смеси, каждому объекту будет сопоставляться тот кластер, вероятность принадлежности к которому будет максимальной.&lt;br /&gt;
&lt;br /&gt;
EM-алгоритм позволяет значительно упростить задачу максимизации правдоподобия выборки путем искусственного введения вспомогательной матрицы скрытых переменных &amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt;. Алгоритм заключается в последовательном повторении шагов E(expectation) и M(maximization):&lt;br /&gt;
* На шаге E на основе текущего приближения параметров смеси по формуле Байеса вычисляются ожидаемые значения скрытых переменных &amp;lt;math&amp;gt;g_{ij}&amp;lt;/math&amp;gt; — апостериорные вероятности того, что &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-й объект принадлежит кластеру &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;.&lt;br /&gt;
* На шаге M решается задача максимизации правдоподобия для нахождения следующего приближения параметров смеси на основе текущего приближения и матрицы скрытых переменных, при этом решение этой задачи выписывается в явном виде.&lt;br /&gt;
&lt;br /&gt;
[[File:EM iterations.png|thumb|center|800px|Рисунок 1. Визуализация компонент смеси после некоторых итераций алгоритма в двумерном пространстве признаков. Для каждой компоненты эллипсами выделены доверительные области с уровнями доверия 0.9, 0.95 и 0.99.]]&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
Пусть заданы &amp;lt;math&amp;gt;l&amp;lt;/math&amp;gt; объектов &amp;lt;math&amp;gt;x_{1},\dotsc,x_{l}&amp;lt;/math&amp;gt;, каждый из которых описывается &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; числовыми признаками. Таким образом, определена матрица объектов-признаков &amp;lt;math&amp;gt;X \in \R^{l \times n}.&amp;lt;/math&amp;gt; Предполагается, что объекты выбраны случайно и независимо из смеси &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;-мерных нормальных распределений с фиксированным числом компонент &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;. Плотность распределения на множестве объектов имеет вид:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;p(x)=\sum_{j=1}^{k}w_{j}p_{j}(x), \ \sum_{j=1}^{k}w_{j}=1, \ w_{j} \ge 0 &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;p_{j}&amp;lt;/math&amp;gt; - плотность распределения &amp;lt;math&amp;gt;j&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;\mu_{j}&amp;lt;/math&amp;gt; и матрицей ковариаций &amp;lt;math&amp;gt;\Sigma_{j}&amp;lt;/math&amp;gt; порядка &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;j = 1,\dotsc,k&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; матрица объектов-признаков &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt;, число кластеров &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;, максимальное число итераций &amp;lt;math&amp;gt;imax&amp;lt;/math&amp;gt;, минимальная величина изменения логарифма правдоподобия &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; набор оценок весов, математических ожиданий и ковариационных матриц компонент смеси &amp;lt;math&amp;gt;\theta = (w_{1},...,w_{k}; \; \mu_{1},...,\mu_{k}; \; \Sigma_{1},...,\Sigma_{k})&amp;lt;/math&amp;gt;, максимизирующий правдоподобие выборки.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Структура алгоритма:&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Инициализация параметров:&#039;&#039;&#039; существует большое число вариантов инициализации параметров распределения. Один из возможных подходов — задание векторов математических ожиданий компонент случайными элементами выборки, задание матриц ковариаций единичными матрицами и задание весов компонент равными &amp;lt;math&amp;gt;\frac{1}{k}.&amp;lt;/math&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;Последовательное выполнение шагов E и M&#039;&#039;&#039; до тех пор, пока правдоподобие выборки не стабилизируется или не будет достигнуто максимальное число итераций:&lt;br /&gt;
** &#039;&#039;&#039;Шаг E:&#039;&#039;&#039; вычисление значений скрытых переменных по формуле Байеса:&lt;br /&gt;
*:&amp;lt;math&amp;gt;g_{ij} = \frac{w_{j} p_{j}(x_{i})}{\sum_{s=1}^{k} w_{s} p_{s}(x_{i})}&amp;lt;/math&amp;gt; , где &amp;lt;math&amp;gt;p_{j}(x_{i}) = \frac{1}{(2\pi)^{n/2}\sqrt{|\Sigma_{j}|}} \exp \biggl( -\frac{1}{2}(x_{i} - \mu_{j})^{T} \Sigma_{j}^{-1} (x_{i} - \mu_{j}) \biggr), \ i = 1,\dotsc,l; \ j = 1,\dotsc,k &amp;lt;/math&amp;gt;&lt;br /&gt;
** &#039;&#039;&#039;Шаг M:&#039;&#039;&#039; перерасчет параметров смеси на основе текущего приближения и матрицы скрытых переменных:&lt;br /&gt;
*:&amp;lt;math&amp;gt;w_{j} = \frac{1}{l} \sum_{i=1}^{l} g_{ij}, \ j = 1,\dotsc,k;&amp;lt;/math&amp;gt;&lt;br /&gt;
*:&amp;lt;math&amp;gt;\mu_{j} = \frac{1}{l w_{j}} \sum_{i=1}^{l} g_{ij} x_{i}, \ j = 1,\dotsc,k;&amp;lt;/math&amp;gt;&lt;br /&gt;
*:&amp;lt;math&amp;gt;\Sigma_{j} = \frac{1}{l w_{j}} \sum_{i=1}^{l} g_{ij}(x_{i} - \mu_{j})(x_{i} - \mu_{j})^T, \ j = 1,\dotsc,k.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро EM-алгоритма — процедура последовательного выполнения шагов E и M:&lt;br /&gt;
* На шаге E на основе текущего приближения параметров смеси вычисляются ожидаемые значения скрытых переменных&lt;br /&gt;
* На шаге M вычисляется следующее приближение параметров смеси на основе текущего приближения и матрицы скрытых переменных&lt;br /&gt;
Наиболее трудоемкой операцией с вычислительной точки зрения является шаг E, в ходе которого производится обращение ковариационных матриц, вычисление их определителей, а также многократное перемножение векторов и матриц при вычислении скрытых переменных.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм состоит из двух итерационно проводимых макроопераций: E-шага и M-шага.&lt;br /&gt;
&lt;br /&gt;
В ходе E-шага используется:&lt;br /&gt;
* Обращение ковариационной матрицы и вычисление ее определителя&lt;br /&gt;
* Умножение вектор-строки на матрицу и вектор-строки на вектор-столбец &lt;br /&gt;
В ходе M-шага используется:&lt;br /&gt;
* Умножение вектор-столбца на вектор-строку&lt;br /&gt;
* Взвешенное суммирование векторов и матриц &lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
# Для всех &amp;lt;math&amp;gt;j = 1,\dotsc,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
#: Инициализировать &amp;lt;math&amp;gt;w_{j}, \ \mu_{j}, \ \Sigma_{j}&amp;lt;/math&amp;gt;&lt;br /&gt;
# Для всех &amp;lt;math&amp;gt;iter = 1,\dotsc,imax&amp;lt;/math&amp;gt;:&lt;br /&gt;
## Шаг E:&lt;br /&gt;
##: Для всех &amp;lt;math&amp;gt;j = 1,\dotsc,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
##:: Вычислить &amp;lt;math&amp;gt;|\Sigma_{j}|, \ \Sigma_{j}^{-1}&amp;lt;/math&amp;gt;&lt;br /&gt;
##: Для всех &amp;lt;math&amp;gt;i = 1,\dotsc,l&amp;lt;/math&amp;gt;:&lt;br /&gt;
##:: &amp;lt;math&amp;gt;sum = 0&amp;lt;/math&amp;gt;&lt;br /&gt;
##:: Для всех &amp;lt;math&amp;gt;j = 1,\dotsc,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
##::: Вычислить &amp;lt;math&amp;gt;p_{j}(x_{i}) = \frac{1}{(2\pi)^{n/2}\sqrt{|\Sigma_{j}|}} \exp \biggl( -\frac{1}{2}(x_{i} - \mu_{j})^{T} \Sigma_{j}^{-1} (x_{i} - \mu_{j}) \biggr)&amp;lt;/math&amp;gt;&lt;br /&gt;
##::: &amp;lt;math&amp;gt;sum = sum + w_{j}p_{j}(x_{i})&amp;lt;/math&amp;gt;&lt;br /&gt;
##:: Для всех &amp;lt;math&amp;gt;j = 1,\dotsc,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
##::: Вычислить &amp;lt;math&amp;gt;g_{ij} = \frac{w_{j} p_{j}(x_{i})}{sum}&amp;lt;/math&amp;gt;&lt;br /&gt;
## Шаг M:&lt;br /&gt;
##: Для всех &amp;lt;math&amp;gt;j = 1,\dotsc,k&amp;lt;/math&amp;gt;:&lt;br /&gt;
##:: Вычислить &amp;lt;math&amp;gt;w_{j} = \frac{1}{l} \sum_{i=1}^{l} g_{ij}&amp;lt;/math&amp;gt;&lt;br /&gt;
##:: Вычислить &amp;lt;math&amp;gt;\mu_{j} = \frac{1}{l w_{j}} \sum_{i=1}^{l} g_{ij} x_{i}&amp;lt;/math&amp;gt;&lt;br /&gt;
##:: Вычислить &amp;lt;math&amp;gt;\Sigma_{j} = \frac{1}{l w_{j}} \sum_{i=1}^{l} g_{ij}(x_{i} - \mu_{j})(x_{i} - \mu_{j})^T&amp;lt;/math&amp;gt;&lt;br /&gt;
## Вычислить изменения логарифма правдоподобия &amp;lt;math&amp;gt;\Delta&amp;lt;/math&amp;gt;&lt;br /&gt;
## Если &amp;lt;math&amp;gt;\Delta &amp;lt; \varepsilon&amp;lt;/math&amp;gt;, то досрочно выйти из цикла&lt;br /&gt;
# Вернуть &amp;lt;math&amp;gt;w_{j}, \mu_{j}, \Sigma_{j}, \ j = 1,\dotsc,k.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
Рассмотрим мультипликативную сложность одной итерации алгоритма:&lt;br /&gt;
* &#039;&#039;&#039;E-шаг:&#039;&#039;&#039;&lt;br /&gt;
** Сложность обращения матрицы ковариаций и вычисления ее определителя — &amp;lt;math&amp;gt;O(n^{3})&amp;lt;/math&amp;gt; (для простоты будем рассматривать метод Гаусса)&lt;br /&gt;
** Сложность вычисления расстояния Махаланобиса (показателя экспоненты) при вычислении значения каждой скрытой переменной — &amp;lt;math&amp;gt;O(n^{2})&amp;lt;/math&amp;gt;&lt;br /&gt;
** Общая сложность E-шага — &amp;lt;math&amp;gt;O(k * n^{3} + k * l * n^{2})&amp;lt;/math&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;M-шаг:&#039;&#039;&#039;&lt;br /&gt;
** Сложность пересчета веса кластера — &amp;lt;math&amp;gt;O(l)&amp;lt;/math&amp;gt;&lt;br /&gt;
** Сложность пересчета центра кластера — &amp;lt;math&amp;gt;O(l * n)&amp;lt;/math&amp;gt;&lt;br /&gt;
** Сложность пересчета матрицы ковариаций кластера — &amp;lt;math&amp;gt;O(l * n)&amp;lt;/math&amp;gt;&lt;br /&gt;
** Общая сложность M-шага — &amp;lt;math&amp;gt;O(k * l * n)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Таким образом, общая сложность одной итерации — &amp;lt;math&amp;gt;O(k * n^{2} * (l + n))&amp;lt;/math&amp;gt;. При учете ограничения на максимальное число итераций получим оценку общей сложности алгоритма — &amp;lt;math&amp;gt;O(imax * k * n^{2} * (l + n))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Большое влияние на сложность E-шага оказывает необходимость обращать ковариационные матрицы и вычислять их определители. Помимо того, что это трудоемкая операция, ковариационные матрицы могут оказаться плохо обусловленными, что может привести к неустойчивости выборочных оценок параметров смеси. Обращения матриц можно избежать, если принять гипотезу о том, что в каждой компоненте смеси признаки некоррелированы, то есть ковариационные матрицы диагональные. В таком случае общая сложность алгоритма составит &amp;lt;math&amp;gt;O(imax * k * n * l)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
На рисунках 2 и 3 представлены информационные графы&amp;lt;ref name=voevodin&amp;gt;Воеводин В.В., Воеводин Вл.В. Параллельные вычисления. - СПб.: БХВ-Петербург, 2002. - 608 с.&amp;lt;/ref&amp;gt; шагов E и M соответственно. Прямоугольниками обозначены входные данные (с пометкой in/out), эллипсами обозначены операции, производимые над данными согласно алгоритму.&lt;br /&gt;
&lt;br /&gt;
Как видно из рисунка 2, E-шаг распадается на:&lt;br /&gt;
* Обращение матриц ковариаций и вычисление их определителей&lt;br /&gt;
* Независимый расчет скрытых переменных по каждому объекту&lt;br /&gt;
&lt;br /&gt;
[[File:E-step.png|thumb|center|1100px|Рисунок 2. Граф шага E с отображением входных и выходных данных.]]&lt;br /&gt;
&lt;br /&gt;
На рисунке 3 видно, что некоторые промежуточные вычисления на шаге M можно проводить независимо для каждого объекта, но после этого придется проводить агрегацию полученных результатов по кластерам.&lt;br /&gt;
&lt;br /&gt;
[[File:M-step.png|thumb|center|1100px|Рисунок 3. Граф шага M с отображением входных и выходных данных.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
Из информационных графов на рисунках 2 и 3 видно, что:&lt;br /&gt;
* Шаг E — наиболее ресурсоемкий этап алгоритма — эффективно распараллеливается по объектам после предварительного обращения матриц ковариаций и вычисления их определителей: при расчете скрытых переменных для фиксированного объекта информация о других объектах не используется. Также стоит отметить, что для всех объектов выполняется одна и та же последовательность действий. Таким образом, параллельная сложность E-шага — &amp;lt;math&amp;gt;O(k * n^{2})&amp;lt;/math&amp;gt;.&lt;br /&gt;
* Менее ресурсоемкий шаг M распараллеливается хуже: промежуточные вычисления можно проводить независимо для каждого объекта, но после этого придется проводить агрегацию полученных результатов по кластерам.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; плотная матрица объектов-признаков &amp;lt;math&amp;gt;X \in \R^{l \times n}&amp;lt;/math&amp;gt;, число кластеров &amp;lt;math&amp;gt;k \in \N&amp;lt;/math&amp;gt;, максимальное число итераций &amp;lt;math&amp;gt;imax \in \N&amp;lt;/math&amp;gt;, минимальная величина изменения логарифма правдоподобия &amp;lt;math&amp;gt;\varepsilon \in \R&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;ln + 3&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039; вещественный вектор весов &amp;lt;math&amp;gt;w \in \R^{k}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; вещественных векторов математических ожиданий &amp;lt;math&amp;gt;\mu_{j} \in \R^{n}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; вещественных ковариационных матриц &amp;lt;math&amp;gt;\Sigma_{j} \in \R^{n \times n}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных:&#039;&#039;&#039; &amp;lt;math&amp;gt;k(n^{2}+n+1)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
Вычислительная мощность EM-алгоритма в предположении о том, что &amp;lt;math&amp;gt;l \gg n&amp;lt;/math&amp;gt; (это условие выполняется в подавляющем большинстве прикладных задач), оценивается величиной &amp;lt;math&amp;gt;O(imax * k * n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Достоинства EM-алгоритма:&lt;br /&gt;
* Мощная математическая основа&lt;br /&gt;
* Слабая чувствительность к выбросам&lt;br /&gt;
* Быстрая сходимость при удачной инициализации параметров&lt;br /&gt;
* Линейный рост сложности при увеличении количества объектов&lt;br /&gt;
&lt;br /&gt;
Недостатки EM-алгоритма:&lt;br /&gt;
* В классическом варианте не может самостоятельно определить количество компонент смеси&lt;br /&gt;
* Трудоемкий и неустойчивый процесс обращения матриц ковариаций в случае несферических компонент смеси&lt;br /&gt;
* Не является детерминированным: в начале работы происходит инициализация начальных параметров случайным образом&lt;br /&gt;
* Не является устойчивым: результат работы сильно зависит от инициализации параметров. При неудачной инициализации может обладать низкой скоростью сходимости, может сойтись к локальному экстремуму или не сойтись вовсе&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
# [http://scikit-learn.org/stable/modules/generated/sklearn.mixture.GaussianMixture.html#sklearn.mixture.GaussianMixture scikit-learn(Python)]&lt;br /&gt;
# [http://docs.opencv.org/2.4/modules/ml/doc/expectation_maximization.html OpenCV(C++/Python)]&lt;br /&gt;
# [http://www.mlpack.org/docs/mlpack-git/doxygen.php?doc=classmlpack_1_1gmm_1_1GMM.html MLPack(C++)]&lt;br /&gt;
# [http://arma.sourceforge.net/docs.html#gmm_diag Armadillo(C++)]&lt;br /&gt;
# [https://www.mathworks.com/help/stats/fitgmdist.html Matlab]&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;/div&gt;</summary>
		<author><name>Algoman</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%90%D0%BB%D0%B5%D0%BA%D1%81%D0%B0%D0%BD%D0%B4%D1%80_%D0%9A%D1%83%D0%B2%D0%B0%D0%B5%D0%B2&amp;diff=15094</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%90%D0%BB%D0%B5%D0%BA%D1%81%D0%B0%D0%BD%D0%B4%D1%80_%D0%9A%D1%83%D0%B2%D0%B0%D0%B5%D0%B2&amp;diff=15094"/>
		<updated>2016-10-31T13:54:36Z</updated>

		<summary type="html">&lt;p&gt;Algoman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Замечания к [[Участник:Александр_Куваев/Алгоритм_кластеризации,_основанный_на_максимизации_ожидания]] ==&lt;br /&gt;
&lt;br /&gt;
1) отсутствует оценка вычислительной мощности алгоритма в п 1.10 - замечание исправлено&lt;br /&gt;
&lt;br /&gt;
== Замечения от 31.10 ==&lt;br /&gt;
&lt;br /&gt;
отсутствует ссылка на источник картинки в п 1.1&lt;br /&gt;
&amp;quot;- В конце статьи должен быть приведен список всех источников, откуда бралась информация по алгоритму. Если вы используется готовый рисунок, то сслыку на источник нужно разместить либо в подписи к рисунку, либо в тексте, где стоит ссылка на рисунок.&amp;quot;&lt;/div&gt;</summary>
		<author><name>Algoman</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%90%D1%80%D1%82%D0%B5%D0%BC_%D0%A2%D0%B0%D1%80%D0%B0%D0%BD&amp;diff=15093</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%90%D1%80%D1%82%D0%B5%D0%BC_%D0%A2%D0%B0%D1%80%D0%B0%D0%BD&amp;diff=15093"/>
		<updated>2016-10-31T13:52:58Z</updated>

		<summary type="html">&lt;p&gt;Algoman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Замечания к [[Участник:Артем_Таран/Графо-ориентированный_алгоритм_кластеризации_CHAMELEON]] ==&lt;br /&gt;
&lt;br /&gt;
1) отсутствует оценка вычислительной мощности алгоритма в п 1.10&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Замечения от 31.10 ==&lt;br /&gt;
&lt;br /&gt;
отсутствует ссылка на источник картинки&lt;br /&gt;
&amp;quot;- В конце статьи должен быть приведен список всех источников, откуда бралась информация по алгоритму. Если вы используется готовый рисунок, то сслыку на источник нужно разместить либо в подписи к рисунку, либо в тексте, где стоит ссылка на рисунок.&amp;quot;&lt;/div&gt;</summary>
		<author><name>Algoman</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%90%D1%80%D1%82%D0%B5%D0%BC_%D0%A2%D0%B0%D1%80%D0%B0%D0%BD&amp;diff=15092</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%90%D1%80%D1%82%D0%B5%D0%BC_%D0%A2%D0%B0%D1%80%D0%B0%D0%BD&amp;diff=15092"/>
		<updated>2016-10-31T13:52:41Z</updated>

		<summary type="html">&lt;p&gt;Algoman: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Замечания к [[Участник:Артем_Таран/Графо-ориентированный_алгоритм_кластеризации_CHAMELEON]] ==&lt;br /&gt;
&lt;br /&gt;
1) отсутствует оценка вычислительной мощности алгоритма в п 1.10&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Замечения от 31.10&lt;br /&gt;
&lt;br /&gt;
отсутсвует ссылка на источник картинки&lt;br /&gt;
&amp;quot;- В конце статьи должен быть приведен список всех источников, откуда бралась информация по алгоритму. Если вы используется готовый рисунок, то сслыку на источник нужно разместить либо в подписи к рисунку, либо в тексте, где стоит ссылка на рисунок.&amp;quot;&lt;/div&gt;</summary>
		<author><name>Algoman</name></author>
	</entry>
</feed>