<?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=Dexter</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=Dexter"/>
	<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/Dexter"/>
	<updated>2026-10-23T01:49:24Z</updated>
	<subtitle>Вклад</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:Dmitry&amp;diff=22131</id>
		<title>Обсуждение участника:Dmitry</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:Dmitry&amp;diff=22131"/>
		<updated>2017-02-04T16:44:27Z</updated>

		<summary type="html">&lt;p&gt;Dexter: /* Статья Участник:Dmitry/Плотностный алгоритм кластеризации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Статья [[Участник:Dmitry/Плотностный алгоритм кластеризации]] ==&lt;br /&gt;
=== Дополнительные замечания ===&lt;br /&gt;
* Врезка - подозрительный объем выходных данных. Это ведь количество кластеров. Оно всегда равно количеству элементов в исходной выборке? Про параллельный алгоритм ничего&lt;br /&gt;
&lt;br /&gt;
* В разделе 1.2 много определений, но ничего про алгоритм. MCP в одной формуле превратилось в MCP.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Замечания по тексту ===&lt;br /&gt;
&lt;br /&gt;
* В разделе 1.4 требуется привести описание алгоритма на верхнем уровне (на основе макроопераций). [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 16:50, 3 февраля 2017 (MSK)&lt;br /&gt;
&lt;br /&gt;
=== Отсутствующие части ===&lt;br /&gt;
* Не заполнен раздел 2.4 описания. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 16:50, 3 февраля 2017 (MSK)&lt;/div&gt;</summary>
		<author><name>Dexter</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%A0%D1%83%D1%81%D0%BB%D0%B0%D0%BD/%D0%9F%D0%BB%D0%BE%D1%82%D0%BD%D0%BE%D1%81%D1%82%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&amp;diff=21132</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%A0%D1%83%D1%81%D0%BB%D0%B0%D0%BD/%D0%9F%D0%BB%D0%BE%D1%82%D0%BD%D0%BE%D1%81%D1%82%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&amp;diff=21132"/>
		<updated>2016-12-17T15:56:30Z</updated>

		<summary type="html">&lt;p&gt;Dexter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Преподаватель 1|Dexter}} &lt;br /&gt;
{{Assignment|Sleo}}&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Плотностный алгоритм кластеризации DBSCAN&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n \log n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(|X| \log |X|)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(m)&amp;lt;/math&amp;gt;&lt;br /&gt;
| 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;
Основной автор описания: [[User:Руслан|Кучеров Р.И.]]&lt;br /&gt;
&lt;br /&gt;
Алгоритм &#039;&#039;&#039;DBSCAN (Density Based Spatial Clustering of Applications with Noise)&#039;&#039;&#039; -  плотностный алгоритм для кластеризации пространственных данных с присутствием шума), был предложен Мартином Эстер, Гансом-Питером Кригель и коллегами в 1996 году как решение проблемы разбиения (изначально пространственных) данных на кластеры произвольной формы. Большинство алгоритмов, производящих плоское разбиение, создают кластеры по форме близкие к сферическим, так как минимизируют расстояние до центра кластера. Авторы DBSCAN экспериментально показали, что их алгоритм способен распознать кластеры различной формы.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритма =&lt;br /&gt;
Кластеризация – это процесс разбиения множества элементов на непересекающиеся кластеры, так, чтобы в каждом кластере все элементы были схожи в каком-то смысле, а объекты разных кластеров существенно отличались.&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Идея, положенная в основу алгоритма, заключается в том, что внутри каждого кластера наблюдается типичная плотность точек (объектов), которая заметно выше, чем плотность снаружи кластера, а также плотность в областях с шумом ниже плотности любого из кластеров. Ещё точнее, что для каждой точки кластера её соседство заданного радиуса должно содержать не менее некоторого числа точек, это число точек задаётся пороговым значением. Алгоритм DBSCAN для заданных значений параметров &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; и MinPts исследует кластер следующим образом: сначала выбирает случайную точку, являющуюся ядровой, в качестве затравки, затем помещает в кластер саму затравку и все точки, плотно-достижимые из неё.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Исходные данные: объекты, которые нужно кластеризовать, параметры &amp;lt;math&amp;gt;MinPts, \ \varepsilon&amp;lt;/math&amp;gt; . Между объектами можно считать расстояния.&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные: разбиение объектов по кластерам. Количество кластеров зависит от исходных данных.&lt;br /&gt;
&lt;br /&gt;
Для построения оценки плотности, на основе соседства точек вводятся понятия достижимости и связности. Под &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; -соседями точки &amp;lt;math&amp;gt;x \in X&amp;lt;/math&amp;gt; понимается множество точек, расстояние до которых не превышает &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; , т. е. &amp;lt;math&amp;gt;N_\varepsilon (x) = \{y \in X | D(x, y) \le \varepsilon\}.&amp;lt;/math&amp;gt; Тогда точка y достижима из точки &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;, если существует последовательность точек &amp;lt;math&amp;gt;x^{(1)}=x, x^{(2)},... , x^{(p-1)}, x^{(p)}=y&amp;lt;/math&amp;gt;, для которой выполнено:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
x^{(i+1)} \in N_\varepsilon (x^{(i)}), i=1,... ,p-1 \\&lt;br /&gt;
\mid N_\varepsilon (x^{(i)}) \mid \ge MinPts, i=1,... ,p-1&lt;br /&gt;
\end{align}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Здесь значение &amp;lt;math&amp;gt;MinPts&amp;lt;/math&amp;gt; задаётся пользователем и регулирует порог «шума». Согласно второму условию, у точек, находящихся внутри кластера, должно быть не менее &amp;lt;math&amp;gt;MinPts \ \varepsilon&amp;lt;/math&amp;gt; -соседей. Такие точки называются «ядрами». Остальные точки разделяются на граничные (имеющие менее &amp;lt;math&amp;gt;MinPts \ \varepsilon&amp;lt;/math&amp;gt; -cоседей, но достижимые из какого-либо «ядра») и шумовые. Две точки связны, если существует «ядро», из которого они обе достижимы. При такой постановке задачи, под кластером понимается максимальное связное подмножество множества X . Точки, не попавшие в какой-либо кластер (не принадлежащие &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; -окрестности какого-либо «ядра»), относятся к классу «шум».&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро последовательной версии зависти от поиска всех точек в &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;-окрестности конкретной точки. Из-за поиска &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;-соседства алгоритм имеет квадратичную вычислительную сложность &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; (где n - количество точек). Но если задействовать K-мерное дерево, то можно снизить сложность до &amp;lt;math&amp;gt;O(\text{n log n})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм DBSCAN использует пространственную структуру данных для определения соседних объектов. Это может быть R*-дерево или k-d дерево. Такие структуры данных позволяют найти все объекты в пределах определенного расстояния от текущего объекта. Также для построения этих деревьев нужно уметь находить расстояние между объектами &amp;lt;math&amp;gt;\rho(u, v)&amp;lt;/math&amp;gt; , в, это расстояние можно вводить разными способами. Например, если &amp;lt;math&amp;gt;\rho(u,v)&amp;lt;/math&amp;gt; - метрика в евклидовом пространстве, &amp;lt;math&amp;gt;u=(u_1,...,u_n)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(v_1,...,v_n)&amp;lt;/math&amp;gt;, то расстояние вычисляется следующим образом: &amp;lt;math&amp;gt;\rho(u,v)=\sqrt{(u_1-v_1)^2+(u_2-v_2)^2+...+(u_n-v_n)^2} = \sqrt{\sum_{k=1}^n(u_k-v_k)^2}.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Алгоритм начинает работу с произвольной точки &amp;lt;math&amp;gt;x \in X&amp;lt;/math&amp;gt; и возвращает &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; -окрестность(строка 4). Если &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;-окрестность содержит, как минимум minpts точек, процедура выдает новый кластер C. Алгоритм извлекает все точки в X, которые являются плотность достижима из x и добавляет их в кластер C(строки 8-17). Если в &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;-окрестности x точек меньше, чем minpts, то x помечается как шум(строка 6). Однако, х все еще может быть добавлены в кластер, если она определится как пограничная точка во время изучения других основных точек(строки 16-17). Поиск точек в &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;-окрестности(функция GETNEIGHBORS)известен, как запрос в диапазоне значений и получает все плотностно достижимые точки от главной точки(строки 8-17) известный как алгоритм наращивания областей. Заметим что кластер может быть определен однозначно, начиная с любой &amp;quot;ядровой&amp;quot; точки&amp;lt;ref&amp;gt; A. Zhou, S. Zhou, J. Cao, Y. Fan, and Y. Hu, “Approaches for scaling DBSCAN algorithm to large spatial databases,” Journal of computer science and technology, vol. 15, no. 6, pp. 509–526, 2000.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    1: procedure DBSCAN(X, eps, minpts)&lt;br /&gt;
    2:     for each unvisited point x ∈ X do&lt;br /&gt;
    3:         mark x as visited&lt;br /&gt;
    4:         N ← GETNEIGHBORS(x, eps)&lt;br /&gt;
    5:         if |N| &amp;lt; minpts then&lt;br /&gt;
    6:             mark x as noise&lt;br /&gt;
    7:         else&lt;br /&gt;
    8:             C ← {x}&lt;br /&gt;
    9:             for each point x&#039; ∈ N do&lt;br /&gt;
    10:                N ← N \ x&#039;&lt;br /&gt;
    11:                if x&#039; is not visited then&lt;br /&gt;
    12:                    mark x&#039; as visited&lt;br /&gt;
    13:                    N&#039; ← GETNEIGHBORS(x&#039;, eps)&lt;br /&gt;
    14:                    if |N&#039;| ≥ minpts then&lt;br /&gt;
    15:                        N ← N ∪ N&#039;&lt;br /&gt;
    16:                if x&#039; is not yet member of any cluster then&lt;br /&gt;
    17:                    C ← C ∪ {x&#039;}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
В общем случае алгоритм DBSCAN имеет квадратичную вычислительную сложность &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;(где n это количество точек в X) из-за поиска &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;-соседства. Но если использовать пространственную индексацию (например, использую k-мерное дерево&amp;lt;ref&amp;gt;M. B. Kennel, “KDTREE 2: Fortran 95 and C++ software to efficiently search for near neighbors in a multi-dimensional Euclidean space,” 2004, institute for Nonlinear Science, University of California.&amp;lt;/ref&amp;gt; или R-дерево) для поиска &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;-соседства, сложность снижается до &amp;lt;math&amp;gt;O(n log n)&amp;lt;/math&amp;gt;&amp;lt;ref&amp;gt;J. Bentley, “Multidimensional binary search trees used for associative searching,” Communications of the ACM, vol. 18, no. 9, pp. 509–517, 1975.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
На рисунке 1 представлен информационный граф алгоритма кластеризации DBSCAN. На входе у нас множество точек &amp;lt;math&amp;gt;P_i&amp;lt;/math&amp;gt; и мы пробегаем по всем непосещенным точкам. Далее мы, для каждой непосещенной точки, маркируем ее как посещенную и находим всех её &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;-соседей(на графике это узел &amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt;). Добавляем точку к кластеру(узел &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;). Затем, пробегаем по всем плотностно-достижимых точках(&amp;lt;math&amp;gt;P_j&amp;lt;/math&amp;gt;) к нашей точке, и для каждой такой точки ищем &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;-сосдей и добавляем их в кластер, если они ещё не принадлежат никакому кластеру.&lt;br /&gt;
&lt;br /&gt;
[[file:Информационный_граф.png|thumb|center|700px|Рис.1  Граф алгоритма без отображения входных и выходных данных. &amp;lt;math&amp;gt;P_i&amp;lt;/math&amp;gt; и  &amp;lt;math&amp;gt;P_j&amp;lt;/math&amp;gt; - точки данного множества, &amp;lt;math&amp;gt;G&amp;lt;/math&amp;gt; - поиск &amp;lt;math&amp;gt;\varepsilon&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;
Поиск &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;-соседей требует вычисления n расстояний и выполнения n сравнений с &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;. Эти операции для каждой пары точек независимы и могут быть выполнены параллельно. Таким образом, при наличии неограниченного числа процессоров сложность поиска составит O(1). Так как поиск выполняется для каждой точки ровно один раз, параллельная сложность всего алгоритма составит O(n).&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Входные данные: набор точек x, пороговое расстояние &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;, а также минимальное количество точек, необходимых для формирования кластера, minpts.&lt;br /&gt;
&lt;br /&gt;
Выход: множество кластеров С.&lt;br /&gt;
&lt;br /&gt;
Если указать маленькое значение &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;, то все точки будут шумом. Если наоборот, сделать большое значение, то кластер не будет разбит, возьмет один кластер и включит в него все точки. Также, если взять minpts слишком большое или слишком маленькое, будет либо один кластер, либо все точки шумовые. Оптимальные значения находятся опытным путем.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
Соотношение последовательной и параллельной сложностей алгоритма является линейным (отношение квадратичной к линейной). При этом вычислительная мощность, как отношение числа операций к суммарному объему входных и выходных данных линейна.&lt;br /&gt;
&lt;br /&gt;
=== Преимущества алгоритма ===&lt;br /&gt;
* не требует указать априори количество кластеров, в отличие от K-средства&lt;br /&gt;
&lt;br /&gt;
* алгоритм может разбить на произвольной формы кластеры. Даже может выявить кластер находящийся внутри другого, но не пересекающийся с ним. Из-за параметра MinPts снижается так называемый эффект однолокальности(single-link)&lt;br /&gt;
&lt;br /&gt;
* алгоритм имеет понятие &amp;quot;шума&amp;quot; и устойчив к выбросам&lt;br /&gt;
&lt;br /&gt;
* алгоритм требует всего два параметра и в основном нечувствительны к упорядоченности изначально данных точек&lt;br /&gt;
&lt;br /&gt;
* параметры MinPts и &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; могут быть установлены, экспертами в какой-либо области, если данные хорошо изучены.&lt;br /&gt;
&lt;br /&gt;
=== Недостатки алгоритма ===&lt;br /&gt;
&lt;br /&gt;
* алгоритм не совсем детерминирован: пограничные точки, которые доступны из более чем одного кластера могут быть частью любого кластера, в зависимости от того, как происходит обработка данных. К счастью, эта ситуация не часто возникают, и мало влияет на результат кластеризации. На основных точках и точках &amp;quot;шума&amp;quot;, алгоритм детерминирован. Есть DBSCAN&amp;lt;ref&amp;gt;Campello, R. J. G. B.; Moulavi, D.; Sander, J. (2013). Density-Based Clustering Based on Hierarchical Density Estimates. Proceedings of the 17th Pacific-Asia Conference on Knowledge Discovery in Databases, PAKDD 2013. Lecture Notes in Computer Science. p. 160.&amp;lt;/ref&amp;gt; который представляет собой вариант, который рассматривает пограничные пункты как шум, и таким образом достигается полностью детерминированный результат, а также более последовательной статистической интерпретации плотности соединенных компонентов.&lt;br /&gt;
&lt;br /&gt;
* качество алогоритма зависит от меры, которую мы рассматриваем в пространстве. Наиболее распространенная мера использует евклидово расстояние. &lt;br /&gt;
 &lt;br /&gt;
* если данные и масштаб не очень хорошо поняты, выбирание значимого расстояния порогового &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; может быть затруднено.&lt;br /&gt;
&lt;br /&gt;
* алгоритм не может кластеризовать данные хорошо с большими различиями в плотности&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
Было проведено исследование масштабируемости параллельной реализации алгоритма DBSCAN. Исследование проводилось на суперкомпьютере &amp;quot;Ломоносов&amp;quot;. Исследовалась параллельная реализация алгоритма, написанная с использованием стандарта MPI. Распараллеливание проводилось по числу входных объектов.&lt;br /&gt;
&lt;br /&gt;
[[file:DbscanPerfomance.png|thumb|center|700px|Рис.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;
[https://github.com/ruslanmsk/parallel_dbscan Параллельная реализация на языке C++]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&amp;lt;span class=&amp;quot;plainlinks&amp;quot;&amp;gt;[//en.wikipedia.org/wiki/ELKI ELKI]&amp;lt;/span&amp;gt; предлагает реализацию DBSCAN, а также GDBSCAN и другие варианты. Эта реализация может использовать различные структуры индексов для поквадратного выполнения и поддерживает произвольное расстояние функции и произвольные типы данных, но это можно обогнать низкоуровневой оптимизацией реализации на небольших наборах данных.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span class=&amp;quot;plainlinks&amp;quot;&amp;gt;[//en.wikipedia.org/wiki/Scikit-learn Scikit-Learn]&amp;lt;/span&amp;gt; включает в себя реализацию Python для DBSCAN для произвольной метрики Минковского, который может быть ускорен с помощью KD-деревьев и шаровых деревьев, но который использует в худшем случае квадратичную память.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span class=&amp;quot;plainlinks&amp;quot;&amp;gt;[//en.wikipedia.org/wiki/R_(programming_language) GNU R]&amp;lt;/span&amp;gt; содержит DBSCAN в [//cran.r-project.org/web/packages/fpc/index.html fpc] пакете с поддержкой произвольных функций расстояния через матриц. Однако он не имеет поддержки индекса (и, соответственно, имеет квадратичное время выполнения и сложность по памяти) и довольно медленно из-за интерпретации R. Более быстрая версия реализована на языке C++ с использованием KD-деревьев (только когда расстояние Евклидово ) в пакете R [//cran.r-project.org/web/packages/dbscan/index.html dbscan].&lt;br /&gt;
&lt;br /&gt;
[//www.philippe-fournier-viger.com/spmf/SPMF SPMF] предлагает GPL-V3 java-реализацию алгоритма DBSCAN с поддержкой KD-дерева (только для параметра расстояние Евклида).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span class=&amp;quot;plainlinks&amp;quot;&amp;gt;[//en.wikipedia.org/wiki/Weka_(machine_learning) Weka]&amp;lt;/span&amp;gt; содержит (как дополнительный пакет в последних версиях) базовую реализацию DBSCAN, которая работает за квадратичное время и линейную память.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span class=&amp;quot;plainlinks&amp;quot;&amp;gt;[//en.wikipedia.org/wiki/Apache_Commons Apache Commons Мath]&amp;lt;/span&amp;gt; содержит java-реализацию алгоритма выполняющегося за квадратичное время.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&lt;br /&gt;
* Ester, Martin, et al. &amp;quot;A density-based algorithm for discovering clusters in large spatial databases with noise.&amp;quot; Kdd. Vol. 96. No. 34. 1996.&lt;br /&gt;
&lt;br /&gt;
* Воеводин В.В. Математические основы параллельных вычислений// М.: Изд. Моск. ун-та, 1991. 345 с.&lt;br /&gt;
&lt;br /&gt;
* Воеводин В.В., Воеводин Вл.В. Параллельные вычисления. – СПб.: БХВ - Петербург, 2002. – 608 с.&lt;br /&gt;
&lt;br /&gt;
* Фролов А.В.. Принципы построения и описание языка Сигма. Препринт ОВМ АН N 236. М.: ОВМ АН СССР, 1989.&lt;/div&gt;</summary>
		<author><name>Dexter</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:Maria_Zaitseva/PAM_(Partitioning_Around_Medoids)&amp;diff=21131</id>
		<title>Участник:Maria Zaitseva/PAM (Partitioning Around Medoids)</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:Maria_Zaitseva/PAM_(Partitioning_Around_Medoids)&amp;diff=21131"/>
		<updated>2016-12-17T15:55:27Z</updated>

		<summary type="html">&lt;p&gt;Dexter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Преподаватель 1|Dexter}} &lt;br /&gt;
{{Assignment|ASA}}&lt;br /&gt;
{{Assignment}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Partitioning Around Medoids&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(Tkn^2)&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;k&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(Tkn)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(k(n-k))&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Авторы: [[Участник: Maria Zaitseva|Зайцева М.Ф.]], [[Участник: kovalexal|Ковальчук А.А.]].&lt;br /&gt;
&lt;br /&gt;
Авторы работали над каждым разделом статьи совместно (совместно искали и изучали материалы, формулировали описание и заполняли описание статьи на сайте). За содержание каждого из пунктов отвечают оба автора.    &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;PAM (Partitioning Around Medoids)&#039;&#039;&#039; – алгоритм разбиения множества объектов на [https://ru.wikipedia.org/wiki/Кластер кластеры], базирующийся на использовании наиболее представительных объектов каждого кластера ([https://ru.wikipedia.org/wiki/Медоид медоидов]) для их описания. Был разработан в 1987 году Леонардом Кауфманом и Питером Русивом &amp;lt;ref&amp;gt;Kaufman L., Rousseeuw P. J. Finding groups in data: an introduction to cluster analysis. – John Wiley &amp;amp; Sons, 2009. – Т. 344.&amp;lt;/ref&amp;gt;. Показывает хорошие результаты разбиения на небольших наборах данных, однако имеет высокую вычислительную сложность, ввиду чего неэффективно работает на больших наборах данных.&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Данный алгоритм используется для решения задачи [https://ru.wikipedia.org/wiki/Кластерный_анализ кластеризации] множества объектов на заранее известное число кластеров &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;
1. Шаг &#039;&#039;BUILD&#039;&#039;. Построение начального набора &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; медоидов путем их последовательного выбора. Первый из них выбирается как объект, сумма дистанций которого до всех других объектов минимальна (центральный объект). Каждый следующий выбирается из оставшихся объектов как лучше всего минимизирующий сумму расстояний от объектов до ближайших к ним медоидов. Выбранный набор медоидов характеризует &amp;quot;конфигурацию&amp;quot; кластеров, для которой может быть вычислена ее стоимость.&lt;br /&gt;
&lt;br /&gt;
2. Шаг &#039;&#039;SWAP&#039;&#039;. На данном шаге производится попытка улучшить стоимость текущей конфигурации путем перебора всех возможных замен (медоид-немедоид). Среди рассматриваемых конфигураций ищется наиболее оптимальная. В случае, если данная конфигурация по стоимости лучше текущей, она принимается в качестве текущей и шаг повторяется с начала, иначе алгоритм завершается.&lt;br /&gt;
&lt;br /&gt;
Преимущества данного алгоритма по сравнению с подобными ему:&lt;br /&gt;
&lt;br /&gt;
* В отличие от более популярного алгоритма [https://ru.wikipedia.org/wiki/K-means k-means], PAM позволяет работать с произвольными объектами с заданной мерой рассчета расстояний (различий), не требует хранения всего множества объектов (достаточно знать лишь матрицу дистанций, так как медоиды выбираются из множества объектов), а также более устойчив к выбросам в данных (за счет рассмотрения медоидов вместо центроидов);&lt;br /&gt;
* В отличие от традиционного [https://en.wikipedia.org/wiki/K-medoids k-medoids] на шаге &#039;&#039;BUILD&#039;&#039; начальные медоиды выбираются более оптимальным образом по сравнению со случайным выбором. Это позволяет уменьшить количество итераций шага &#039;&#039;SWAP&#039;&#039;, тем самым сокращая время работы алгоритма.&lt;br /&gt;
&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;o = \{1,\dots,n\} \subset \mathbb{Z}&amp;lt;/math&amp;gt; –– множество индексов объектов&lt;br /&gt;
* &amp;lt;math&amp;gt;O = \{O_1,\dots,O_n\}&amp;lt;/math&amp;gt; –– множество объектов&lt;br /&gt;
* &amp;lt;math&amp;gt;k \leq n&amp;lt;/math&amp;gt; –– количество кластеров для разбиения&lt;br /&gt;
* &amp;lt;math&amp;gt;d:O\times O\rightarrow \mathbb{R}^{1}&amp;lt;/math&amp;gt; –– метрика расчета расстояний между объектами, &amp;lt;math&amp;gt;d_{ij} = d(O_i,O_j)&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;D\in \mathbb{R}^{n\times n}&amp;lt;/math&amp;gt; –– симметрическая матрица дистанций объектов, где &amp;lt;math&amp;gt;D=(d_{ij}), i \in o, j \in o&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;m = \{m_1,\dots,m_k\}\subset o&amp;lt;/math&amp;gt; –– множество индексов объектов, принятых в качестве медоидов; &amp;lt;math&amp;gt; M &amp;lt;/math&amp;gt;--множество медоидов.&lt;br /&gt;
&lt;br /&gt;
Принадлежность объекта к определенному кластеру определяется как индекс ближайшего к нему медоида:&lt;br /&gt;
:&amp;lt;math&amp;gt;g_m(i)=\arg \min_{m_j\in m} d_{im_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Основная задача состоит в выборе такого множества индексов медоидов &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, наилучшим образом минимизирующего функционал:&lt;br /&gt;
:&amp;lt;math&amp;gt;F_o(m) = \sum_{j \in o \backslash m} d_{jg_m(j)}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Введем обозначения:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;D_j = d_{jg_m(j)}&amp;lt;/math&amp;gt; –– индекс первого по близости к j медоида&lt;br /&gt;
* &amp;lt;math&amp;gt;E_j = d_{jg_{m \backslash g_m(j)}(j)}&amp;lt;/math&amp;gt; –– индекс второго по близости к j медоида&lt;br /&gt;
&lt;br /&gt;
Решение задачи состоит из следующих шагов:&lt;br /&gt;
&lt;br /&gt;
1. Шаг &#039;&#039;BUILD&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
  1.1. Выбор первого медоида&lt;br /&gt;
:&amp;lt;math&amp;gt;m=\{ \arg \min_{i \in o} \sum_{j \in o} d_{ij} \}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  1.2 Последовательный выбор оставшихся медоидов до тех пор, пока &amp;lt;math&amp;gt;\left\vert{m}\right\vert \neq k&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;m = m \cup \{ \arg \max_{i \in o \backslash m} \sum_{j \in o \backslash \{m \cup i\} } \max (D_j - d_{ji}, 0) \}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. Шаг &#039;&#039;SWAP&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
  2.1. Производится перебор всех возможных пар медоид-немедоид &amp;lt;math&amp;gt;(i, h): i \in m, h \in o \backslash m&amp;lt;/math&amp;gt;, для каждой из которых рассчитывается стоимость смены текущей конфигурации &amp;lt;math&amp;gt;T_m(i,h)&amp;lt;/math&amp;gt;. При смене конфигурации множество медоидов изменяется &amp;lt;math&amp;gt;m = m \cup \{h\} \backslash \{i\}&amp;lt;/math&amp;gt;.&lt;br /&gt;
:&amp;lt;math&amp;gt;T_m(i, h) = \sum_{j \in o \backslash \{m \cup h\}} C_{jih}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;C_{jih}&amp;lt;/math&amp;gt; –– вклад объекта &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; в перестановку медоида &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; и не медоида &amp;lt;math&amp;gt;h&amp;lt;/math&amp;gt;.&lt;br /&gt;
  При этом &amp;lt;math&amp;gt;C_{jih}&amp;lt;/math&amp;gt; рассчитывается по-разному в зависимости от положения &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; относительно &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;h&amp;lt;/math&amp;gt; (&amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; дальше от &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; и от &amp;lt;math&amp;gt;h&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;j&amp;lt;/math&amp;gt; оказался дальше от &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;, но ближе к &amp;lt;math&amp;gt;h&amp;lt;/math&amp;gt;, чем к своему медоиду).&lt;br /&gt;
:&amp;lt;math&amp;gt;C_{jih} = \left\{\begin{matrix}&lt;br /&gt;
0, &amp;amp; d_{ji} &amp;gt;  D_j, d_{jh} &amp;gt;  D_j \\ &lt;br /&gt;
d_{jh} - d_{ji}, &amp;amp; d_{ji} = D_j, d_{jh} &amp;lt; E_j \\ &lt;br /&gt;
E_j - D_j, &amp;amp; d_{ji} = D_j, d_{jh} \geqslant  E_j \\ &lt;br /&gt;
d_{jh} - D_j, &amp;amp; d_{ji} &amp;gt;  D_j, d_{jh} &amp;lt;  D_j &lt;br /&gt;
\end{matrix}\right.&amp;lt;/math&amp;gt;&lt;br /&gt;
  Среди всех пар находится такая пара &amp;lt;math&amp;gt;(i_s, h_s)&amp;lt;/math&amp;gt;, что &amp;lt;math&amp;gt;T_m(i_s, h_s)&amp;lt;/math&amp;gt; минимально.&lt;br /&gt;
&lt;br /&gt;
  2.2 В случае, если &amp;lt;math&amp;gt;T_m(i_s, h_s) \geq 0&amp;lt;/math&amp;gt;, смена конфигурации медоидов не производится и решение задачи окончено. Иначе производится смена конфигурации и повторяется шаг 2.1.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
Вычислительное ядро алгоритма на этапе &#039;&#039;BUILD&#039;&#039; состоит последовательного выбора такого объекта из числа немедоидов, добавление которого к множеству медоидов максимизирует следующую функцию:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;F_{m} = \max_{i \in o \backslash m} \sum_{j \in o \backslash \{m \cup i\} } \max (D_j - d_{ji}, 0)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С каждой следующей итерацией множество просматриваемых немедоидов уменьшается, таким образом, на &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом шаге итерации необходимо рассчитывать сумму для &amp;lt;math&amp;gt;n - i&amp;lt;/math&amp;gt; немедоидов.&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро алгоритма на этапе &#039;&#039;SWAP&#039;&#039; состоит в расчете функции минимизации стоимости изменения конфигурации &amp;lt;math&amp;gt;T_m(i, h)&amp;lt;/math&amp;gt; при замене медоида &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; на немедоид &amp;lt;math&amp;gt;h&amp;lt;/math&amp;gt; в текущей конфигурации для всех возможных &amp;lt;math&amp;gt;(i, h): i \in m, h \in o \backslash m&amp;lt;/math&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;T_m(i, h) = \sum_{j \in o \backslash \{m \cup h\}} C_{jih}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
1. Макрооперация &amp;quot;Выбор следующего медоида&amp;quot;&lt;br /&gt;
:&amp;lt;math&amp;gt;m = m \cup \{ \arg \max_{i \in o \backslash m} \sum_{j \in o \backslash \{m \cup i\} } \max (D_j - d_{ji}, 0) \}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. Макрооперация &amp;quot;Вычисление стоимости смены текущей конфигурации&amp;quot;&lt;br /&gt;
:&amp;lt;math&amp;gt;T_m(i, h) = \sum_{j \in o \backslash \{m \cup h\}} C_{jih}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Таким образом, алгоритм, в терминах макроопераций выглядит следующим образом:&lt;br /&gt;
&lt;br /&gt;
1. Фаза &#039;&#039;BUILD&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
На данном шаге осуществляется выбор первого медоида. Далее осуществляется макрооперация &amp;quot;Выбор следующего медоида&amp;quot; &amp;lt;math&amp;gt;(k - 1)&amp;lt;/math&amp;gt; раз.&lt;br /&gt;
&lt;br /&gt;
2. Фаза &#039;&#039;SWAP&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
На данном шаге для всех возможных комбинаций медоид-немедоид осуществляется макрооперация &amp;quot;Вычисление стоимости смены текущей конфигурации&amp;quot;. Данная операция производится &amp;lt;math&amp;gt;k(n-k)&amp;lt;/math&amp;gt; раз для каждой итерации. Среди всех комбинаций выбирается та замена, стоимость которой максимальна.&lt;br /&gt;
&lt;br /&gt;
3. &#039;&#039;Критерий останова&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;T_m(i, h) &amp;lt; 0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Псевдокод алгоритма&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;Вход&#039;&#039;&#039;: Объем входных данных: &amp;lt;math&amp;gt;n\times n + 2&amp;lt;/math&amp;gt;. Матрица дистанций D (&amp;lt;math&amp;gt;n\times n&amp;lt;/math&amp;gt; вещественных чисел); количество кластеров &amp;lt;math&amp;gt;k \in \mathbb{Z}&amp;lt;/math&amp;gt;; максимальное количество итераций алгоритма &amp;lt;math&amp;gt;maxIter \in \mathbb{Z}&amp;lt;/math&amp;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;m = \{m_1, \dots, m_k\} \subset \mathbb{Z}&amp;lt;/math&amp;gt;&lt;br /&gt;
 1 # Фаза BUILD&lt;br /&gt;
 2 Выбор стартового объекта в качестве начального медоида: m = {первый медоид}&lt;br /&gt;
 3 Пока |m| != k:&lt;br /&gt;
 4     Выбор следующего медоида i_m&lt;br /&gt;
 5     Добавление найденного медоида в множество: m = m + {i_m}&lt;br /&gt;
 6 # Фаза SWAP&lt;br /&gt;
 7 Пока (maxIter--):&lt;br /&gt;
 8     Лучшая стоимость замены: Tbest = MAXINT&lt;br /&gt;
 9     Кандидаты на замену: (i_s, h_s) = (-1, -1)&lt;br /&gt;
 10     Для всех i из множества медоидов:&lt;br /&gt;
 11         Для всех j из множества немедоидов:&lt;br /&gt;
 12             Расчет стоимости замены Tm(i,h)&lt;br /&gt;
 13             Если Tm(i, h) &amp;lt; Tbest:&lt;br /&gt;
 14                 Tbest = Tm(i, j)&lt;br /&gt;
 15                 Запомнить найденные кандидаты: (i_s, j_s) = (i, h)&lt;br /&gt;
 16     Если Tbest &amp;gt;= 0:&lt;br /&gt;
 17         Выход&lt;br /&gt;
 18     Иначе:&lt;br /&gt;
 19         m = m + {h} - {i}&lt;br /&gt;
&lt;br /&gt;
На фазе &#039;&#039;BUILD&#039;&#039; осуществляется построение начального множества медоидов. Данный процесс производится итерационно до тех пор, пока не будет найдено необходимое число медоидов.&lt;br /&gt;
На фазе &#039;&#039;SWAP&#039;&#039; производится попытка улучшить множество выбранных медоидов. Данный процесс также производится итерационно то тех пор, пока целевая функция не перестанет улучшаться. Также, для данного шага можно ввести ограничение по числу производимых алгоритмом итераций.&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Для осуществления шага &#039;&#039;BUILD&#039;&#039; потребуется:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;n^2&amp;lt;/math&amp;gt; операций сложения и &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; операций сравнения для выбора начального медоида;&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{l=1}^{k-1} (2(n-l) \cdot (n-l-1)+(n-l))=\frac{1}{6}(k-1)(4k^2 - 12kn + k + 6n(2n-1))&amp;lt;/math&amp;gt; операций сложения, вычитания и сравнения для всех итераций выбора медоидов.&lt;br /&gt;
&lt;br /&gt;
Таким образом, последовательная сложность шага &#039;&#039;BUILD&#039;&#039; оценивается как &amp;lt;math&amp;gt;O(kn^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Для осуществления каждого шага &#039;&#039;SWAP&#039;&#039; потребуется:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;2k(n-k)(n-k-1)&amp;lt;/math&amp;gt; операций вычитания и сложения;&lt;br /&gt;
* &amp;lt;math&amp;gt;k(n-k)&amp;lt;/math&amp;gt; операций сравнения;&lt;br /&gt;
&lt;br /&gt;
Таким образом, последовательная сложность каждого шага &#039;&#039;SWAP&#039;&#039; оценивается как &amp;lt;math&amp;gt;O(kn^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
Заранее число итераций шага &#039;&#039;SWAP&#039;&#039; неизвестно, поэтому принимаем его равным &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;. Отсюда, общая последовательная сложность алгоритма PAM оценивается как &amp;lt;math&amp;gt;O(Tkn^2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф шага BUILD ===&lt;br /&gt;
На рис.1 показана информационная структура шага BUILD алгоритма PAM на некотором шаге.&lt;br /&gt;
&lt;br /&gt;
[[file:Pam_build.png|thumb|center|553px|Рис.1. Информационная структура шага BUILD алгоритма PAM на шаге &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Операции&#039;&#039;:&lt;br /&gt;
* &amp;lt;math&amp;gt;sum_{o,m_t}(i) = \sum_{j \in o \backslash \{m \cup i\}} \max (D_j, d_{ji})&amp;lt;/math&amp;gt; –– оценка конфигурации при внесении &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; в множество индексов медоидов &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; с множеством объектов &amp;lt;math&amp;gt;o&amp;lt;/math&amp;gt;;&lt;br /&gt;
* &amp;lt;math&amp;gt;\arg \max&amp;lt;/math&amp;gt; –– индекс объекта, дающего наибольшую оценку конфигурации при его внесении в множество индексов медоидов &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;;&lt;br /&gt;
* &amp;lt;math&amp;gt;update(m)&amp;lt;/math&amp;gt; –– операция добавления индекса объекта в множество индексов медоидов &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф шага SWAP ===&lt;br /&gt;
На рис.2 показана информационная структура шага SWAP алгоритма PAM на некотором шаге.&lt;br /&gt;
&lt;br /&gt;
[[file:Pam_swap_new.png|thumb|center|553px|Рис.2. Информационная структура шага SWAP алгоритма PAM на шаге &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Операции&#039;&#039;:&lt;br /&gt;
* &amp;lt;math&amp;gt;T_m(i, h) = \sum_{j \in o \backslash \{m \cup h\}} C_{jih} &amp;lt;/math&amp;gt; –– стоимость смены конфигурации при замене немедоида &amp;lt;math&amp;gt;h&amp;lt;/math&amp;gt; медоидом &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; в текущей конфигурации &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;;&lt;br /&gt;
* &amp;lt;math&amp;gt;\arg \min&amp;lt;/math&amp;gt; –– пара &amp;lt;math&amp;gt;(i, h)&amp;lt;/math&amp;gt; (медоид-немедоид), замена которой в текущей конфигурации &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; дает наименьшую стоимость смены;&lt;br /&gt;
* &amp;lt;math&amp;gt;swap&amp;lt;/math&amp;gt; –– операция замены медоида &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; на немедоид &amp;lt;math&amp;gt;h&amp;lt;/math&amp;gt; в текущей конфигурации &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;, если стоимость смены отрицательна.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Для осуществления шага &#039;&#039;BUILD&#039;&#039; потребуется:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; параллельных операций сложения и &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; последовательных операций сравнения для выбора начального медоида;&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{l=1}^{k-1} 2(n-l) = (k-1)(2n-k)&amp;lt;/math&amp;gt; параллельных операций сложения и вычитания для всех итераций выбора медоидов;&lt;br /&gt;
* &amp;lt;math&amp;gt;\sum_{l=1}^{k-1} n-l = \frac{1}{2}(k-1)(2n-k)&amp;lt;/math&amp;gt; последовательных операций сравнения для всех итераций выбора медоидов.&lt;br /&gt;
&lt;br /&gt;
Таким образом, параллельная сложность шага &#039;&#039;BUILD&#039;&#039; оценивается как &amp;lt;math&amp;gt;O(kn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Для осуществления каждого шага &#039;&#039;SWAP&#039;&#039; потребуется:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;k(n-k) &amp;lt;/math&amp;gt; параллельных операций вычитания и сложения;&lt;br /&gt;
* &amp;lt;math&amp;gt;k(n-k)&amp;lt;/math&amp;gt; последовательных операций сравнения.&lt;br /&gt;
&lt;br /&gt;
Таким образом, параллельная сложность каждого шага &#039;&#039;SWAP&#039;&#039; оценивается как &amp;lt;math&amp;gt;O(kn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
Заранее число итераций шага &#039;&#039;SWAP&#039;&#039; неизвестно, поэтому принимаем его равным &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;. Отсюда, общая параллельная сложность алгоритма PAM оценивается как &amp;lt;math&amp;gt;O(Tkn)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Входные данные&#039;&#039;:&lt;br /&gt;
* Массив &amp;lt;math&amp;gt;V&amp;lt;/math&amp;gt; из &amp;lt;math&amp;gt;\frac{n(n-1)}{2}&amp;lt;/math&amp;gt; вещественных чисел, определяющий набор дистанций между всеми парами объектов (сжатая матрица дистанций). Симметрическая матрица дистанций  &amp;lt;math&amp;gt;D\in \mathbb{R}^{n\times n}&amp;lt;/math&amp;gt;  восстанавливается из этого массива однозначным образом (для восстановления необходимо знать число объектов &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;):&lt;br /&gt;
:&amp;lt;math&amp;gt;D(i, j)=\left\{\begin{matrix}&lt;br /&gt;
V[ni - \frac{i(i + 1)}{2} + (j - i - 1)], &amp;amp; i &amp;lt; j\\ &lt;br /&gt;
V[nj - \frac{j(j + 1)}{2} + (i - j - 1)], &amp;amp; i &amp;gt; j \\&lt;br /&gt;
0, &amp;amp; i = j&lt;br /&gt;
\end{matrix}\right.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Целое число кластеров &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;, на которое необходимо разбить множество объектов.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Выходные данные&#039;&#039;:&lt;br /&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;i&amp;lt;/math&amp;gt; можно восстановить с использованием функции &amp;lt;math&amp;gt;g_m(i)=\arg \min_{m_j\in m} d_{im_j}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
1. &#039;&#039;Соотношение последовательной и параллельной сложности&#039;&#039; в случае неограниченных ресурсов является &#039;&#039;линейным&#039;&#039; как отношение квадратичной сложности к линейной.  &lt;br /&gt;
&lt;br /&gt;
2. &#039;&#039;Вычислительная мощность&#039;&#039; последовательного алгоритма, как отношение числа операций к суммарному объему входных и выходных данных: &amp;lt;math&amp;gt; O(Tk) &amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
3. Алгоритм является &#039;&#039;устойчивым&#039;&#039;, так как все операции в алгоритме не подвержены накоплению ошибки.&lt;br /&gt;
&lt;br /&gt;
4. Алгоритм является &#039;&#039;не детерминированным&#039;&#039;, так как  не детерминирован выбор набора медоидов, на которых достигается наилучшая конфигурация.&lt;br /&gt;
&lt;br /&gt;
5. Имеет высокую вычислительную сложность (квадратичную) ввиду необходимости полного перебора, поэтому неэффективно работает на больших наборах данных.&lt;br /&gt;
&lt;br /&gt;
6. Позволяет работать с произвольными объектами с заданной мерой рассчета расстояний (различий), не требует хранения всего множества объектов.&lt;br /&gt;
&lt;br /&gt;
7. Устойчив к выбросам данных (за счет рассмотрения медоидов).&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
Для изучения масштабируемости алгоритма была выполнена его [https://gitlab.com/kovalexal/pam-lomonosov реализация] с использованием механизма MPI на языке программирования C++. Данная реализация использует библиотеку [http://www.boost.org Boost] (модуль MPI для удобного взаимодействия C++ и MPI и модуль uBLAS для работы с матрицами). Исследование масштабируемости описанной реализации производилось на суперкомпьютере [https://parallel.ru/cluster/lomonosov.html &amp;quot;Ломоносов&amp;quot;]. Для сборки программы использовался компилятор gcc версии 5.2.0 с опциями &amp;quot;-std=c++11 -O3&amp;quot; совместно с OpenMPI версии 1.8.4.&lt;br /&gt;
&lt;br /&gt;
В качестве рассматриваемого при оценке набора данных была произведена их генерация на основе двумерного нормального распределения. Для этого сперва выбиралось некоторое количество точек, которые в дальнейшем выступали в качестве центроидов кластеров. Далее, для каждого полученного кластера осуществлялась генерация равного числа точек.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[file:points.png|thumb|center|553px|Рис.3. Пример сгенерированных данных – 20 кластеров, 5000 точек]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Набор значений параметров запуска, используемых для оценке масштабируемости представлен ниже:&lt;br /&gt;
&lt;br /&gt;
* Число процессов: [1, 8, 16, 32, 48, 50, 51, 64, 99, 100, 101, 128, 160, 192, 200, 224, 256, 320, 384, 448, 512]&lt;br /&gt;
* Число кластеризуемых элементов: от 1000 до 5000 с шагом 250&lt;br /&gt;
* Число кластеров при расчете: 20&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Для оценки производительности алгоритма осуществлялся расчет числа операций с плавающей запятой в секунду (FLOPs или GFLOPs). Для этого при каждом запуске рассчитывалось время работы алгоритма, число итераций шага &#039;&#039;SWAP&#039;&#039;, по данным значениям можно получить точное число операций сложения, вычитания и сравнения вещественных чисел (оно равно последовательной сложности алгоритма), поделив его на время работы можно получить оценку числа FLOP в секунду. График изменения производительности в зависимости от числа процессоров и числа кластеризуемых элементов представлен ниже. Интерактивный график доступен по [https://plot.ly/~kovalexal/7/ ссылке].&lt;br /&gt;
&lt;br /&gt;
[[file:PAM_perf.png|thumb|center|553px|Рис.4. Изменение производительности в зависимости от числа процессоров и числа кластеризуемых элементов]]&lt;br /&gt;
&lt;br /&gt;
Масштабируемость алгоритма была получена путем деления реальной производительности на пиковую произвдительность &amp;lt;math&amp;gt;s&amp;lt;/math&amp;gt; задействованных ядер (пиковая производительность одного ядра &amp;quot;Ломоносова&amp;quot; составляет &#039;&#039;5.686&#039;&#039; GFLOPs). График изменения эффективности в зависимости от числа процессоров и числа кластеризуемых элементов представлен ниже. Интерактивный график доступен по [https://plot.ly/~kovalexal/9/ ссылке].&lt;br /&gt;
&lt;br /&gt;
[[file:PAM_eff.png|thumb|center|553px|Рис.5. Изменение эффективности в зависимости от числа процессоров и числа кластеризуемых элементов]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Из полученных значений эффективности можно оценить диапазон эффективности реализации алгоритма:&lt;br /&gt;
&lt;br /&gt;
* минимальная эффективность: 0.10353% достигается при использовании 512 процессов для кластеризации 1000 элементов на 20 кластеров;&lt;br /&gt;
* максимальная эффективность: 0.47637% достигается при использовании 1 процесса для кластеризации 2000 элементов на 20 кластеров.&lt;br /&gt;
&lt;br /&gt;
Построим оценки масштабируемости выбранной реализации алгоритма Partitioning Around Medoids согласно [[Scalability_methodology]]:&lt;br /&gt;
&lt;br /&gt;
* По числу процессов: 6.07542E-04. При увеличении числа процессов эффективность реализации на рассмотренной области значений параметров запуска возрастает, но интенсивность данного роста мала. Для увеличения масштабируемости по числу процессов необходимо увеличить количество операций в секунду, осуществляемых каждым процессом (например, уменьшив время работы алгоритма). Для этого можно применить различные технологии распараллеливания и векторизации вычислений.&lt;br /&gt;
* По размеру задачи: 1.91151E-04. При увеличении размера задачи эффективность возрастает, однако данный рост достаточно слаб. Это говорит нам о том, что эффективность алгоритма слабо зависит от размера входной задачи. &lt;br /&gt;
* По двум направлениям: 2.03868E-05. При рассмотрении увеличения как размера входа, так и числа процессов на всей рассмотренной области значений эффективность увеличивается, однако скорость увеличения эффективности небольшая. В совокупности с тем фактом, что разница между минимальной и максимальной эффективностью на рассмотренной области параметров небольшая, эффективность с увеличением масштабов возрастает, но медленно.&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. Последовательные реализации&lt;br /&gt;
&lt;br /&gt;
* В [https://www.mathworks.com/help/stats/kmedoids.html?requestedDomain=www.mathworks.com#namevaluepairs MATLAB] ([https://ru.wikipedia.org/wiki/Коммерческое_программное_обеспечение Commercial software])&lt;br /&gt;
* [http://elki.dbs.ifi.lmu.de/browser/elki/elki/src/main/java/de/lmu/ifi/dbs/elki/algorithm/clustering/kmeans/KMedoidsPAM.java ELKI] на языке JAVA (Свободное распространение ([https://ru.wikipedia.org/wiki/GNU_Affero_General_Public_License AGPL]))&lt;br /&gt;
* В пакете [https://cran.r-project.org/package=cluster Cluster] на языке R (Свободное распространение ([https://ru.wikipedia.org/wiki/GNU_General_Public_License#GPL_v1 GPL]))&lt;br /&gt;
* В пакете [https://cran.r-project.org/package=ClusterR ClusterR] на языке R (Свободное распространение ([https://ru.wikipedia.org/wiki/Лицензия_MIT MIT]))&lt;br /&gt;
&lt;br /&gt;
2. Параллельные реализации&lt;br /&gt;
&lt;br /&gt;
* В пакете [https://cran.r-project.org/package=sprint SPRINT] на языке R (Свободное распространение ([https://ru.wikipedia.org/wiki/GNU_General_Public_License#GPL_v1 GPL]))&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&lt;br /&gt;
[[en:Description of algorithm properties and structure]]&lt;/div&gt;</summary>
		<author><name>Dexter</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=21051</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=21051"/>
		<updated>2016-12-16T11:09:06Z</updated>

		<summary type="html">&lt;p&gt;Dexter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Преподаватель 1|Dexter}}&lt;br /&gt;
&lt;br /&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;
Под &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;.&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;U. \cdot V&amp;lt;/math&amp;gt;,&lt;br /&gt;
* Поэлементного деления вектора на вектор &amp;lt;math&amp;gt;U. / 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>Dexter</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9A%D0%B0%D0%B7%D0%B0%D0%BA%D0%BE%D0%B2_%D0%90%D1%80%D1%82%D0%B5%D0%BC/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BE%D0%BD%D1%86%D0%B5%D0%BF%D1%82%D1%83%D0%B0%D0%BB%D1%8C%D0%BD%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_COBWEB&amp;diff=20756</id>
		<title>Участник:Казаков Артем/Алгоритм концептуальной кластеризации COBWEB</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9A%D0%B0%D0%B7%D0%B0%D0%BA%D0%BE%D0%B2_%D0%90%D1%80%D1%82%D0%B5%D0%BC/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BE%D0%BD%D1%86%D0%B5%D0%BF%D1%82%D1%83%D0%B0%D0%BB%D1%8C%D0%BD%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_COBWEB&amp;diff=20756"/>
		<updated>2016-12-12T14:27:31Z</updated>

		<summary type="html">&lt;p&gt;Dexter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Преподаватель 1|Dexter}}&lt;br /&gt;
{{Assignment|ASA}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Алгоритм концептуальной кластеризации COBWEB &lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(N*logN*B^{2}AV)&amp;lt;/math&amp;gt;&lt;br /&gt;
| parallel_complexity = &amp;lt;math&amp;gt;O(N*logN*log(BAV))&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Автор статьи: [[Участник: Казаков Артем|Артем Казаков]] (группа 624)&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Алгоритм &#039;&#039;&#039;COBWEB&#039;&#039;&#039;&amp;lt;ref name=&amp;quot;wiki&amp;quot; /&amp;gt;&amp;lt;ref name=&amp;quot;paper&amp;quot; /&amp;gt; — классический метод инкрементальной концептуальной кластеризации. Он создаёт иерархическую кластеризацию в виде дерева классификации: каждый узел этого дерева ссылается на концепт (концепт — описание группы объектов через определенный набор пар аттрибут-значение) и содержит вероятностное описание этого концепта, которое включает в себя вероятность принадлежности концепта к данному узлу.&amp;lt;ref name=&amp;quot;habr&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Узлы, находящейся на определённом уровне дерева классификации, называют срезом. Алгоритм использует для построения дерева классификации эвристическую меру оценки, называемую полезностью категории — прирост ожидаемого числа корректных предположений о значениях атрибутов при знании об их принадлежности к определённой категории относительно ожидаемого числа корректных предположений о значениях атрибутов без этого знания. Чтобы встроить новый объект в дерево классификации, алгоритм &#039;&#039;&#039;COBWEB&#039;&#039;&#039; итеративно проходит всё дерево в поисках «лучшего» узла, к которому отнести этот объект. Выбор узла осуществляется на основе помещения объекта в каждый узел и вычисления полезности категории получившегося среза. Также вычисляется полезность категории для случая, когда объект относится к вновь создаваемому узлу. В итоге объект относится к тому узлу, для которого полезность категории наибольшая.&lt;br /&gt;
&lt;br /&gt;
Однако &#039;&#039;&#039;COBWEB&#039;&#039;&#039; имеет ряд ограничений. Во-первых, он предполагает, что распределения вероятностей значений различных атрибутов статистически независимы друг от друга. Однако это предположение не всегда верно, потому как часто между значениями атрибутов существует корреляция. Во-вторых, вероятностное представление кластеров делает очень сложным их обновление, особенно в том случае, когда атрибуты имеют большое число возможных значений. Это вызвано тем, что сложность алгоритма зависит не только от количества атрибутов, но и от количества их возможных значений.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Обозначим:&lt;br /&gt;
* &amp;lt;math&amp;gt;\{ A_{1}, A_{2}, ... \}&amp;lt;/math&amp;gt; — множество свойств кластеризуемых объектов&lt;br /&gt;
* &amp;lt;math&amp;gt;\{ u_{1j}, u_{2j}, ... \}&amp;lt;/math&amp;gt; —  возможнные значения свойства &amp;lt;math&amp;gt;A_{j}&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;\{ C_{1}, C_{2}, ... \}&amp;lt;/math&amp;gt; — множество категорий&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;P(A_j = u_{ij} | C_k)&amp;lt;/math&amp;gt; — это условная вероятность, с которой свойство &amp;lt;math&amp;gt;A_{j}&amp;lt;/math&amp;gt;, принимает значение &amp;lt;math&amp;gt;u_{ij}&amp;lt;/math&amp;gt;, если объект относится к категории &amp;lt;math&amp;gt;C_{k}&amp;lt;/math&amp;gt;. Для каждой категории в иерархии определены вероятности вхождения всех значений каждого свойства. При предъявлении нового экземпляра система &#039;&#039;&#039;COBWEB&#039;&#039;&#039; оценивает качество отнесения этого примера к существующей категории и модификации иерархии категорий в соответствии с новым представителем. Критерием оценки качества классификации является полезность категории (&#039;&#039;category utility&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Критерий полезности категории максимизирует вероятность того, что два объекта, отнесенные к одной категории, имеют одинаковые значения свойств и значения свойств для объектов из различных категорий отличаются. Полезность категории определяется формулой&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CU = \sum_{k} \sum_{i} \sum_{j} P(A_j = u_{ij}|C_k) P(C_k|A_j = u_{ij}) P(A_j = u_{ij})&amp;lt;/math&amp;gt;&amp;lt;ref name=&amp;quot;shit&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Значения суммируются по всем категориям &amp;lt;math&amp;gt;C_k&amp;lt;/math&amp;gt;, всем свойствам &amp;lt;math&amp;gt;A_j&amp;lt;/math&amp;gt; и всем значениям свойств &amp;lt;math&amp;gt;u_{ij}&amp;lt;/math&amp;gt;. Значение &amp;lt;math&amp;gt;P(A_j = u_{ij} | C_k)&amp;lt;/math&amp;gt; называется предсказуемостью (predictability). Это вероятность того, что объект, для которого свойство &amp;lt;math&amp;gt;A_j&amp;lt;/math&amp;gt; принимает значение &amp;lt;math&amp;gt;u_{ij}&amp;lt;/math&amp;gt;, относится к категории &amp;lt;math&amp;gt;C_k&amp;lt;/math&amp;gt;. Чем выше это значение, тем вероятнее, что свойства двух объектов, отнесенных к одной категории, имеют одинаковые значения. Величина &amp;lt;math&amp;gt;P(C_k | A = u_{ij})&amp;lt;/math&amp;gt; называется предиктивностью (predictiveness). Это вероятность того, что для объектов из категории &amp;lt;math&amp;gt;C_k&amp;lt;/math&amp;gt; свойство &amp;lt;math&amp;gt;A_j&amp;lt;/math&amp;gt; принимает значение &amp;lt;math&amp;gt;u_{ij}&amp;lt;/math&amp;gt;. Чем больше эта величина, тем менее вероятно, что для объектов, не относящихся к данной категории, это свойство будет принимать указанное значение. Значение &amp;lt;math&amp;gt;P(A = u_{ij})&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;
* &amp;lt;math&amp;gt;B&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;A&amp;lt;/math&amp;gt; — числа свойств у классифицируемых объектов&lt;br /&gt;
* &amp;lt;math&amp;gt;V&amp;lt;/math&amp;gt; — среднее число значений, которые могут принимать свойства&lt;br /&gt;
&lt;br /&gt;
На каждом шаге алгоритма (всего &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; производится спуск по дереву (&amp;lt;math&amp;gt;O(log_{B}N)&amp;lt;/math&amp;gt;). На каждой итерации спуска производится &amp;lt;math&amp;gt;O(B)&amp;lt;/math&amp;gt; вычислений полезности категории &amp;lt;math&amp;gt;CU&amp;lt;/math&amp;gt;, вычисление каждой из которых имеет сложность &amp;lt;math&amp;gt;O(BAV)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Перемножив сложности выше получам сложность из п. 1.6., что подтверждает, что основная часть вычислительных операций приходится именно на вычисление полезностей категорий.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
В алгоритме &#039;&#039;&#039;COBWEB&#039;&#039;&#039; реализован метод поиска экстремума в пространстве возможных кластеров с использованием критерия полезности категорий для оценки и выбора возможных способов категоризации.&lt;br /&gt;
&lt;br /&gt;
* Сначала вводится единственная категория, свойства которой совпадают со свойствами первого экземпляра. &lt;br /&gt;
* Для каждого последующего экземпляра алгоритм начинает свою работу с корневой категории и движется далее по дереву. &lt;br /&gt;
* На каждом уровне выполняется оценка эффективности категоризации на основе полезности категории. При этом оцениваются результаты следующих операций:&lt;br /&gt;
** Отнесение экземпляра к наилучшей из существующих категорий.&lt;br /&gt;
** Добавление новой категории, содержащей единственный экземпляр.&lt;br /&gt;
** Слияние двух существующих категорий в одну новую с добавлением в нее этого экземпляра.&lt;br /&gt;
** Разбиение существующей категории на две и отнесение экземпляра к лучшей из вновь созданных категорий.&lt;br /&gt;
* Для слияния двух узлов создается новый узел, для которого существующие узлы становятся дочерними. На основе значений вероятностей дочерних узлов вычисляются вероятности для нового узла. При разбиении один узел заменяется двумя дочерними.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Алгоритм повторяется для каждого нового объекта. В данном алгоритме происходит спуск по дереву и на каждом шаге спуска выбирается одно из действий описанных в п. 1.4.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;cobweb(Node, Instance)&lt;br /&gt;
 Begin&lt;br /&gt;
  if узел Node - это лист, then&lt;br /&gt;
    begin&lt;br /&gt;
     создать два дочерних узла L1 и L2 для узла Node;&lt;br /&gt;
     задать для узла L1 те же вероятности, что и для узла Node;&lt;br /&gt;
     инициализировать вероятности для узла L2 соответствующими значениями объекта Instance;&lt;br /&gt;
     добавить Instance к Node, обновив вероятности для узла Node ;&lt;br /&gt;
    end&lt;br /&gt;
  else&lt;br /&gt;
    begin&lt;br /&gt;
     добавить Instance к Node, обновив вероятности для узла Node;&lt;br /&gt;
     для каждого дочернего узла С узла Node вычислить полезность категории при отнесении экземпляра Instance к категории С;&lt;br /&gt;
     пусть S1 - значение полезности для наилучшей классификации C1;&lt;br /&gt;
     пусть S2 - значение для второй наилучшей классификации C2;&lt;br /&gt;
     пусть S3 - значение полезности для отнесения экземпляра к новой категории;&lt;br /&gt;
     пусть S4 - значение для слияния C1 и C2 в одну категорию;&lt;br /&gt;
     пусть S5 - значение для разделения C1 (замены дочерними категориями);&lt;br /&gt;
    end&lt;br /&gt;
   if S1 - максимальное значение CU, then&lt;br /&gt;
     cobweb(C1, Instance) %отнести экземпляр к C1&lt;br /&gt;
   else&lt;br /&gt;
     if S3 - максимальное значение CU, then&lt;br /&gt;
       инициализировать вероятности для новой категории Cm значениями Instance &lt;br /&gt;
     else &lt;br /&gt;
       if S4 - максимальное значение CU, then &lt;br /&gt;
         begin&lt;br /&gt;
           пусть Cm - результат слияния C1 и C2; &lt;br /&gt;
           cobweb(Cm, Instance);&lt;br /&gt;
         end &lt;br /&gt;
       else&lt;br /&gt;
         if S5 - максимальное значение CU, then &lt;br /&gt;
           begin &lt;br /&gt;
             разделить C1; % Cm - новая категория&lt;br /&gt;
             cobweb(Cm, Instance)&lt;br /&gt;
           end;&lt;br /&gt;
 end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Последовательная сложность алгоритма равна &amp;lt;math&amp;gt;O(N*log_{B}N*B^{2}AV)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где:&lt;br /&gt;
* &amp;lt;math&amp;gt;B&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;A&amp;lt;/math&amp;gt; — числа свойств у классифицируемых объектов&lt;br /&gt;
* &amp;lt;math&amp;gt;V&amp;lt;/math&amp;gt; — среднее число значений, которые могут принимать свойства&lt;br /&gt;
&lt;br /&gt;
Обоснование сложности приводится в п. 1.3.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
[[file:Cobweb-flow-2.png|thumb|center|750px|Рис. 1 Информационный граф алгоритма COBWEB]]&lt;br /&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;N_{11}, N_{12}, ..., N_{1L}&amp;lt;/math&amp;gt; — узлы первого уровня&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;N_{21}, N_{22}, ..., N_{2L}&amp;lt;/math&amp;gt; — узлы второго уровня&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;N_{B1}, N_{B2}, ..., N_{BL}&amp;lt;/math&amp;gt; — узлы последнего уровня&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_1, C_2, ..., C_L&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;
* При неограниченном ресурсе параллелизма, вычисление функции полезности может быть произведено за &amp;lt;math&amp;gt;O(log(BAV))&amp;lt;/math&amp;gt; через независимое вычисление каждой её составной части (за &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;) и последующую их параллельную редукцию за &amp;lt;math&amp;gt;O(log(q))&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q=BAV&amp;lt;/math&amp;gt; — количество составных частей функции полезности.&lt;br /&gt;
* Вычисление совокупности функций полезности (которых &amp;lt;math&amp;gt;O(B)&amp;lt;/math&amp;gt;) также может быть распараллелено c последующей параллельной редукцией за &amp;lt;math&amp;gt;O(log(B))&amp;lt;/math&amp;gt; и итоговой параллельной сложностью &amp;lt;math&amp;gt;O(log(BAV)+log(B))=log(BAV))&amp;lt;/math&amp;gt; (при неограниченном ресурсе параллелизма).&lt;br /&gt;
* Продвижение объектов по дереву может не может быть распараллелено, поскольку входные данные для каждой очередной итерации зависят от результата выполнения предыдущей. Всего за время работы алгоритма выполняется &amp;lt;math&amp;gt;O(N*logN)&amp;lt;/math&amp;gt; операций продвижения по дереву.&lt;br /&gt;
&lt;br /&gt;
Таким образом, итоговая параллельная сложность алгоритма равна &amp;lt;math&amp;gt;N*logN*log(BAV)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
На вход алгоритм принимает множество объектов, характеризуемых набором свойств. В свою очередь, каждое свойство может принимать какое-либо значение из множества допустимых значений. Оценка объема входных данных составляет &amp;lt;math&amp;gt;O(N*A)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Результатом работы алгоритма является построенное дерево классификации, листья которого представляют собой различные классы объектов и содержат сами объекты принадлежащие данному классу. Оценка объема выходных данных составляет &amp;lt;math&amp;gt;O(N*logN)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Этот алгоритм достаточно эффективен и выполняет кластеризацию на разумное число классов. Поскольку в нем используется вероятностное представление принадлежности, получаемые категории являются гибкими и робастными. Кроме того, в нем проявляется эффект категорий базового уровня, поддерживается прототипирование и учитывается степень принадлежности. Он основан не на классической логике, а, подобно методам теории нечетких множеств, учитывает &amp;quot;неопределенность&amp;quot; категоризации как необходимый компонент обучения и рассуждений в гибкой и интеллектуальной манере.&lt;br /&gt;
&lt;br /&gt;
Оценка вычислительной мощности алгоритма составляет &amp;lt;math&amp;gt;O(N * B * V * (A + logN))&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;
Исследование масштабируемости параллельной реализации алгоритма COBWEB проводилось на компьютере с процессором Intel(R) Core(TM) i7-5960X @ 4.30GHz, который поддерживает до 12ти потоков при наличии 6 физических ядер. Была взята реализация алгоритма COBWEB на Python из библиотки Concept Formation&amp;lt;ref name=&amp;quot;gh_cf&amp;quot; /&amp;gt; и распараллелена с использованием средств Python multiprocessing&amp;lt;ref&amp;gt;https://docs.python.org/3.5/library/multiprocessing.html — библиотека multiprocessing для распараллеливания программ на Python&amp;lt;/ref&amp;gt;.&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;
* Количество объектов для кластеризации &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;: 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000&lt;br /&gt;
* Количество процессоров &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;: 1, 2, 3, 4, 5, 6&lt;br /&gt;
* Версия Python: 3.5&lt;br /&gt;
&lt;br /&gt;
Данные выбирались из стандартной библиотеки тестовых данных Библиоткеи Concept Formation (mushrooms).&lt;br /&gt;
&lt;br /&gt;
Для заданной конфигурации эксперимента и полученным результатам [[Глоссарий#Производительность|производительность]] и эффективность реализации расчитывались по формулам:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;Perf = \frac{N_{op}}{t}\ \ (FLOPS),&amp;lt;/math&amp;gt;,&lt;br /&gt;
где &amp;lt;math&amp;gt;N_{op}&amp;lt;/math&amp;gt; &amp;amp;mdash; точное число операций с плавающей точкой (операции с памятью, а также целочисленные операции не учитывались), вычисленное в соответствие с разделом [[#Последовательная сложность алгоритма| &amp;quot;Последовательная сложность алгоритма&amp;quot;]];&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;Efficiency = \frac{100 * Performance}{Perf_{Peak}^{p}}\ \ (%),&amp;lt;/math&amp;gt;,&lt;br /&gt;
где &amp;lt;math&amp;gt;Perf_{Peak}^{p}&amp;lt;/math&amp;gt; &amp;amp;ndash; пиковая производительность суперкомпьютера при &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; процессорах, вычисленная согласно спецификациям Intel&amp;lt;sup&amp;gt;&amp;amp;reg;&amp;lt;/sup&amp;gt; Core i7&amp;lt;sup&amp;gt;&amp;amp;reg;&amp;lt;/sup&amp;gt; X5960&amp;lt;ref&amp;gt;&amp;quot;http://ark.intel.com/ru/products/82930/Intel-Core-i7-5960X-Processor-Extreme-Edition-20M-Cache-up-to-3_50-GHz&amp;quot;&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Графики зависимости производительности и эффективности параллельной реализации COBWEB от числа векторов для кластеризации (&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;) и числа процессоров (&amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;) представлены ниже.&lt;br /&gt;
&lt;br /&gt;
[[file:Cobwebtime.png|thumb|center|640px|Рис. 2 Время работы алгоритма COBWEB в зависимости от числа процессов и размера задачи]]&lt;br /&gt;
[[file:Cobwebeff.png|thumb|center|640px|Рис. 3 Эффективность алгоритма COBWEB в зависимости от числа процессов и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
Таким образом можно сделать вывод о том, что данная реализация обладает слабой масштабируемостью. Во многом это связано с высокими накладными расходами на параллелизм в среде исполнения Python.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Существуют следующие реализации алгоритма COBWEB:&lt;br /&gt;
* [https://github.com/cmaclell/concept_formation/ Concept Formation]&amp;lt;ref name=&amp;quot;gh_cf&amp;quot;&amp;gt;https://github.com/cmaclell/concept_formation/ — библиотека, содержащая реализации алгоритмов COBWEB и COBWEB/3 для языка Python&amp;lt;/ref&amp;gt; библиотека, содержащая реализации алгоритмов COBWEB и COBWEB/3 для языка Python.&lt;br /&gt;
* [http://www.cs.waikato.ac.nz/~ml/weka Weka]&amp;lt;ref&amp;gt;http://www.cs.waikato.ac.nz/~ml/weka — библиотека и инструмент для анализа данных на языке Java&amp;lt;/ref&amp;gt; библиотека и инструмент для анализа данных на языке Java.&lt;br /&gt;
* [http://java-ml.sourceforge.net/ Java-ML] &amp;lt;ref&amp;gt;http://java-ml.sourceforge.net/ — библиотека машинного обучения на языке Java&amp;lt;/ref&amp;gt; библиотека машинного обучения на языке Java.&lt;br /&gt;
&lt;br /&gt;
Так как существуют алгоритмы кластеризации, обладающие лучшими свойствами, алгоритм COBWEB практически не применяется и параллельных реализаций этого алгоритма нет.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&amp;lt;references&amp;gt;&lt;br /&gt;
&amp;lt;ref name=&amp;quot;wiki&amp;quot;&amp;gt;https://en.wikipedia.org/wiki/Cobweb_(clustering) — описание алгоритма на Википедии (Eng)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;ref name=&amp;quot;habr&amp;quot;&amp;gt;https://habrahabr.ru/post/164417/ — сравнение алгоритма COBWEB с другими алгоритмами кластеризации&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;ref name=&amp;quot;shit&amp;quot;&amp;gt;http://bourabai.ru/tpoi/analysis6.htm — подробное описание алгоритма COBWEB&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;ref name=&amp;quot;paper&amp;quot;&amp;gt;http://www.cl.cam.ac.uk/~av308/cobweb.pdf — статья, в которой алгоритм COBWEB был впервые представлем&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;/references&amp;gt;&lt;/div&gt;</summary>
		<author><name>Dexter</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9A%D0%B0%D0%B7%D0%B0%D0%BA%D0%BE%D0%B2_%D0%90%D1%80%D1%82%D0%B5%D0%BC/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BE%D0%BD%D1%86%D0%B5%D0%BF%D1%82%D1%83%D0%B0%D0%BB%D1%8C%D0%BD%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_COBWEB&amp;diff=20755</id>
		<title>Участник:Казаков Артем/Алгоритм концептуальной кластеризации COBWEB</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9A%D0%B0%D0%B7%D0%B0%D0%BA%D0%BE%D0%B2_%D0%90%D1%80%D1%82%D0%B5%D0%BC/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BE%D0%BD%D1%86%D0%B5%D0%BF%D1%82%D1%83%D0%B0%D0%BB%D1%8C%D0%BD%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_COBWEB&amp;diff=20755"/>
		<updated>2016-12-12T14:27:00Z</updated>

		<summary type="html">&lt;p&gt;Dexter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{Assignment|Преподаватель 1|Dexter}}&lt;br /&gt;
{{Assignment|ASA}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Алгоритм концептуальной кластеризации COBWEB &lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(N*logN*B^{2}AV)&amp;lt;/math&amp;gt;&lt;br /&gt;
| parallel_complexity = &amp;lt;math&amp;gt;O(N*logN*log(BAV))&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Автор статьи: [[Участник: Казаков Артем|Артем Казаков]] (группа 624)&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Алгоритм &#039;&#039;&#039;COBWEB&#039;&#039;&#039;&amp;lt;ref name=&amp;quot;wiki&amp;quot; /&amp;gt;&amp;lt;ref name=&amp;quot;paper&amp;quot; /&amp;gt; — классический метод инкрементальной концептуальной кластеризации. Он создаёт иерархическую кластеризацию в виде дерева классификации: каждый узел этого дерева ссылается на концепт (концепт — описание группы объектов через определенный набор пар аттрибут-значение) и содержит вероятностное описание этого концепта, которое включает в себя вероятность принадлежности концепта к данному узлу.&amp;lt;ref name=&amp;quot;habr&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Узлы, находящейся на определённом уровне дерева классификации, называют срезом. Алгоритм использует для построения дерева классификации эвристическую меру оценки, называемую полезностью категории — прирост ожидаемого числа корректных предположений о значениях атрибутов при знании об их принадлежности к определённой категории относительно ожидаемого числа корректных предположений о значениях атрибутов без этого знания. Чтобы встроить новый объект в дерево классификации, алгоритм &#039;&#039;&#039;COBWEB&#039;&#039;&#039; итеративно проходит всё дерево в поисках «лучшего» узла, к которому отнести этот объект. Выбор узла осуществляется на основе помещения объекта в каждый узел и вычисления полезности категории получившегося среза. Также вычисляется полезность категории для случая, когда объект относится к вновь создаваемому узлу. В итоге объект относится к тому узлу, для которого полезность категории наибольшая.&lt;br /&gt;
&lt;br /&gt;
Однако &#039;&#039;&#039;COBWEB&#039;&#039;&#039; имеет ряд ограничений. Во-первых, он предполагает, что распределения вероятностей значений различных атрибутов статистически независимы друг от друга. Однако это предположение не всегда верно, потому как часто между значениями атрибутов существует корреляция. Во-вторых, вероятностное представление кластеров делает очень сложным их обновление, особенно в том случае, когда атрибуты имеют большое число возможных значений. Это вызвано тем, что сложность алгоритма зависит не только от количества атрибутов, но и от количества их возможных значений.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
Обозначим:&lt;br /&gt;
* &amp;lt;math&amp;gt;\{ A_{1}, A_{2}, ... \}&amp;lt;/math&amp;gt; — множество свойств кластеризуемых объектов&lt;br /&gt;
* &amp;lt;math&amp;gt;\{ u_{1j}, u_{2j}, ... \}&amp;lt;/math&amp;gt; —  возможнные значения свойства &amp;lt;math&amp;gt;A_{j}&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;\{ C_{1}, C_{2}, ... \}&amp;lt;/math&amp;gt; — множество категорий&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;P(A_j = u_{ij} | C_k)&amp;lt;/math&amp;gt; — это условная вероятность, с которой свойство &amp;lt;math&amp;gt;A_{j}&amp;lt;/math&amp;gt;, принимает значение &amp;lt;math&amp;gt;u_{ij}&amp;lt;/math&amp;gt;, если объект относится к категории &amp;lt;math&amp;gt;C_{k}&amp;lt;/math&amp;gt;. Для каждой категории в иерархии определены вероятности вхождения всех значений каждого свойства. При предъявлении нового экземпляра система &#039;&#039;&#039;COBWEB&#039;&#039;&#039; оценивает качество отнесения этого примера к существующей категории и модификации иерархии категорий в соответствии с новым представителем. Критерием оценки качества классификации является полезность категории (&#039;&#039;category utility&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Критерий полезности категории максимизирует вероятность того, что два объекта, отнесенные к одной категории, имеют одинаковые значения свойств и значения свойств для объектов из различных категорий отличаются. Полезность категории определяется формулой&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CU = \sum_{k} \sum_{i} \sum_{j} P(A_j = u_{ij}|C_k) P(C_k|A_j = u_{ij}) P(A_j = u_{ij})&amp;lt;/math&amp;gt;&amp;lt;ref name=&amp;quot;shit&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Значения суммируются по всем категориям &amp;lt;math&amp;gt;C_k&amp;lt;/math&amp;gt;, всем свойствам &amp;lt;math&amp;gt;A_j&amp;lt;/math&amp;gt; и всем значениям свойств &amp;lt;math&amp;gt;u_{ij}&amp;lt;/math&amp;gt;. Значение &amp;lt;math&amp;gt;P(A_j = u_{ij} | C_k)&amp;lt;/math&amp;gt; называется предсказуемостью (predictability). Это вероятность того, что объект, для которого свойство &amp;lt;math&amp;gt;A_j&amp;lt;/math&amp;gt; принимает значение &amp;lt;math&amp;gt;u_{ij}&amp;lt;/math&amp;gt;, относится к категории &amp;lt;math&amp;gt;C_k&amp;lt;/math&amp;gt;. Чем выше это значение, тем вероятнее, что свойства двух объектов, отнесенных к одной категории, имеют одинаковые значения. Величина &amp;lt;math&amp;gt;P(C_k | A = u_{ij})&amp;lt;/math&amp;gt; называется предиктивностью (predictiveness). Это вероятность того, что для объектов из категории &amp;lt;math&amp;gt;C_k&amp;lt;/math&amp;gt; свойство &amp;lt;math&amp;gt;A_j&amp;lt;/math&amp;gt; принимает значение &amp;lt;math&amp;gt;u_{ij}&amp;lt;/math&amp;gt;. Чем больше эта величина, тем менее вероятно, что для объектов, не относящихся к данной категории, это свойство будет принимать указанное значение. Значение &amp;lt;math&amp;gt;P(A = u_{ij})&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;
* &amp;lt;math&amp;gt;B&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;A&amp;lt;/math&amp;gt; — числа свойств у классифицируемых объектов&lt;br /&gt;
* &amp;lt;math&amp;gt;V&amp;lt;/math&amp;gt; — среднее число значений, которые могут принимать свойства&lt;br /&gt;
&lt;br /&gt;
На каждом шаге алгоритма (всего &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; производится спуск по дереву (&amp;lt;math&amp;gt;O(log_{B}N)&amp;lt;/math&amp;gt;). На каждой итерации спуска производится &amp;lt;math&amp;gt;O(B)&amp;lt;/math&amp;gt; вычислений полезности категории &amp;lt;math&amp;gt;CU&amp;lt;/math&amp;gt;, вычисление каждой из которых имеет сложность &amp;lt;math&amp;gt;O(BAV)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Перемножив сложности выше получам сложность из п. 1.6., что подтверждает, что основная часть вычислительных операций приходится именно на вычисление полезностей категорий.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
В алгоритме &#039;&#039;&#039;COBWEB&#039;&#039;&#039; реализован метод поиска экстремума в пространстве возможных кластеров с использованием критерия полезности категорий для оценки и выбора возможных способов категоризации.&lt;br /&gt;
&lt;br /&gt;
* Сначала вводится единственная категория, свойства которой совпадают со свойствами первого экземпляра. &lt;br /&gt;
* Для каждого последующего экземпляра алгоритм начинает свою работу с корневой категории и движется далее по дереву. &lt;br /&gt;
* На каждом уровне выполняется оценка эффективности категоризации на основе полезности категории. При этом оцениваются результаты следующих операций:&lt;br /&gt;
** Отнесение экземпляра к наилучшей из существующих категорий.&lt;br /&gt;
** Добавление новой категории, содержащей единственный экземпляр.&lt;br /&gt;
** Слияние двух существующих категорий в одну новую с добавлением в нее этого экземпляра.&lt;br /&gt;
** Разбиение существующей категории на две и отнесение экземпляра к лучшей из вновь созданных категорий.&lt;br /&gt;
* Для слияния двух узлов создается новый узел, для которого существующие узлы становятся дочерними. На основе значений вероятностей дочерних узлов вычисляются вероятности для нового узла. При разбиении один узел заменяется двумя дочерними.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Алгоритм повторяется для каждого нового объекта. В данном алгоритме происходит спуск по дереву и на каждом шаге спуска выбирается одно из действий описанных в п. 1.4.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;cobweb(Node, Instance)&lt;br /&gt;
 Begin&lt;br /&gt;
  if узел Node - это лист, then&lt;br /&gt;
    begin&lt;br /&gt;
     создать два дочерних узла L1 и L2 для узла Node;&lt;br /&gt;
     задать для узла L1 те же вероятности, что и для узла Node;&lt;br /&gt;
     инициализировать вероятности для узла L2 соответствующими значениями объекта Instance;&lt;br /&gt;
     добавить Instance к Node, обновив вероятности для узла Node ;&lt;br /&gt;
    end&lt;br /&gt;
  else&lt;br /&gt;
    begin&lt;br /&gt;
     добавить Instance к Node, обновив вероятности для узла Node;&lt;br /&gt;
     для каждого дочернего узла С узла Node вычислить полезность категории при отнесении экземпляра Instance к категории С;&lt;br /&gt;
     пусть S1 - значение полезности для наилучшей классификации C1;&lt;br /&gt;
     пусть S2 - значение для второй наилучшей классификации C2;&lt;br /&gt;
     пусть S3 - значение полезности для отнесения экземпляра к новой категории;&lt;br /&gt;
     пусть S4 - значение для слияния C1 и C2 в одну категорию;&lt;br /&gt;
     пусть S5 - значение для разделения C1 (замены дочерними категориями);&lt;br /&gt;
    end&lt;br /&gt;
   if S1 - максимальное значение CU, then&lt;br /&gt;
     cobweb(C1, Instance) %отнести экземпляр к C1&lt;br /&gt;
   else&lt;br /&gt;
     if S3 - максимальное значение CU, then&lt;br /&gt;
       инициализировать вероятности для новой категории Cm значениями Instance &lt;br /&gt;
     else &lt;br /&gt;
       if S4 - максимальное значение CU, then &lt;br /&gt;
         begin&lt;br /&gt;
           пусть Cm - результат слияния C1 и C2; &lt;br /&gt;
           cobweb(Cm, Instance);&lt;br /&gt;
         end &lt;br /&gt;
       else&lt;br /&gt;
         if S5 - максимальное значение CU, then &lt;br /&gt;
           begin &lt;br /&gt;
             разделить C1; % Cm - новая категория&lt;br /&gt;
             cobweb(Cm, Instance)&lt;br /&gt;
           end;&lt;br /&gt;
 end&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Последовательная сложность алгоритма равна &amp;lt;math&amp;gt;O(N*log_{B}N*B^{2}AV)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где:&lt;br /&gt;
* &amp;lt;math&amp;gt;B&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;A&amp;lt;/math&amp;gt; — числа свойств у классифицируемых объектов&lt;br /&gt;
* &amp;lt;math&amp;gt;V&amp;lt;/math&amp;gt; — среднее число значений, которые могут принимать свойства&lt;br /&gt;
&lt;br /&gt;
Обоснование сложности приводится в п. 1.3.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
[[file:Cobweb-flow-2.png|thumb|center|750px|Рис. 1 Информационный граф алгоритма COBWEB]]&lt;br /&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;N_{11}, N_{12}, ..., N_{1L}&amp;lt;/math&amp;gt; — узлы первого уровня&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;N_{21}, N_{22}, ..., N_{2L}&amp;lt;/math&amp;gt; — узлы второго уровня&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;N_{B1}, N_{B2}, ..., N_{BL}&amp;lt;/math&amp;gt; — узлы последнего уровня&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;C_1, C_2, ..., C_L&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;
* При неограниченном ресурсе параллелизма, вычисление функции полезности может быть произведено за &amp;lt;math&amp;gt;O(log(BAV))&amp;lt;/math&amp;gt; через независимое вычисление каждой её составной части (за &amp;lt;math&amp;gt;O(1)&amp;lt;/math&amp;gt;) и последующую их параллельную редукцию за &amp;lt;math&amp;gt;O(log(q))&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;q=BAV&amp;lt;/math&amp;gt; — количество составных частей функции полезности.&lt;br /&gt;
* Вычисление совокупности функций полезности (которых &amp;lt;math&amp;gt;O(B)&amp;lt;/math&amp;gt;) также может быть распараллелено c последующей параллельной редукцией за &amp;lt;math&amp;gt;O(log(B))&amp;lt;/math&amp;gt; и итоговой параллельной сложностью &amp;lt;math&amp;gt;O(log(BAV)+log(B))=log(BAV))&amp;lt;/math&amp;gt; (при неограниченном ресурсе параллелизма).&lt;br /&gt;
* Продвижение объектов по дереву может не может быть распараллелено, поскольку входные данные для каждой очередной итерации зависят от результата выполнения предыдущей. Всего за время работы алгоритма выполняется &amp;lt;math&amp;gt;O(N*logN)&amp;lt;/math&amp;gt; операций продвижения по дереву.&lt;br /&gt;
&lt;br /&gt;
Таким образом, итоговая параллельная сложность алгоритма равна &amp;lt;math&amp;gt;N*logN*log(BAV)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
На вход алгоритм принимает множество объектов, характеризуемых набором свойств. В свою очередь, каждое свойство может принимать какое-либо значение из множества допустимых значений. Оценка объема входных данных составляет &amp;lt;math&amp;gt;O(N*A)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Результатом работы алгоритма является построенное дерево классификации, листья которого представляют собой различные классы объектов и содержат сами объекты принадлежащие данному классу. Оценка объема выходных данных составляет &amp;lt;math&amp;gt;O(N*logN)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Этот алгоритм достаточно эффективен и выполняет кластеризацию на разумное число классов. Поскольку в нем используется вероятностное представление принадлежности, получаемые категории являются гибкими и робастными. Кроме того, в нем проявляется эффект категорий базового уровня, поддерживается прототипирование и учитывается степень принадлежности. Он основан не на классической логике, а, подобно методам теории нечетких множеств, учитывает &amp;quot;неопределенность&amp;quot; категоризации как необходимый компонент обучения и рассуждений в гибкой и интеллектуальной манере.&lt;br /&gt;
&lt;br /&gt;
Оценка вычислительной мощности алгоритма составляет &amp;lt;math&amp;gt;O(N * B * V * (A + logN))&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;
Исследование масштабируемости параллельной реализации алгоритма COBWEB проводилось на компьютере с процессором Intel(R) Core(TM) i7-5960X @ 4.30GHz, который поддерживает до 12ти потоков при наличии 6 физических ядер. Была взята реализация алгоритма COBWEB на Python из библиотки Concept Formation&amp;lt;ref name=&amp;quot;gh_cf&amp;quot; /&amp;gt; и распараллелена с использованием средств Python multiprocessing&amp;lt;ref&amp;gt;https://docs.python.org/3.5/library/multiprocessing.html — библиотека multiprocessing для распараллеливания программ на Python&amp;lt;/ref&amp;gt;.&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;
* Количество объектов для кластеризации &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;: 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000&lt;br /&gt;
* Количество процессоров &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;: 1, 2, 3, 4, 5, 6&lt;br /&gt;
* Версия Python: 3.5&lt;br /&gt;
&lt;br /&gt;
Данные выбирались из стандартной библиотеки тестовых данных Библиоткеи Concept Formation (mushrooms).&lt;br /&gt;
&lt;br /&gt;
Для заданной конфигурации эксперимента и полученным результатам [[Глоссарий#Производительность|производительность]] и эффективность реализации расчитывались по формулам:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;Perf = \frac{N_{op}}{t}\ \ (FLOPS),&amp;lt;/math&amp;gt;,&lt;br /&gt;
где &amp;lt;math&amp;gt;N_{op}&amp;lt;/math&amp;gt; &amp;amp;mdash; точное число операций с плавающей точкой (операции с памятью, а также целочисленные операции не учитывались), вычисленное в соответствие с разделом [[#Последовательная сложность алгоритма| &amp;quot;Последовательная сложность алгоритма&amp;quot;]];&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;Efficiency = \frac{100 * Performance}{Perf_{Peak}^{p}}\ \ (%),&amp;lt;/math&amp;gt;,&lt;br /&gt;
где &amp;lt;math&amp;gt;Perf_{Peak}^{p}&amp;lt;/math&amp;gt; &amp;amp;ndash; пиковая производительность суперкомпьютера при &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; процессорах, вычисленная согласно спецификациям Intel&amp;lt;sup&amp;gt;&amp;amp;reg;&amp;lt;/sup&amp;gt; Core i7&amp;lt;sup&amp;gt;&amp;amp;reg;&amp;lt;/sup&amp;gt; X5960&amp;lt;ref&amp;gt;&amp;quot;http://ark.intel.com/ru/products/82930/Intel-Core-i7-5960X-Processor-Extreme-Edition-20M-Cache-up-to-3_50-GHz&amp;quot;&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Графики зависимости производительности и эффективности параллельной реализации COBWEB от числа векторов для кластеризации (&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;) и числа процессоров (&amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;) представлены ниже.&lt;br /&gt;
&lt;br /&gt;
[[file:Cobwebtime.png|thumb|center|640px|Рис. 2 Время работы алгоритма COBWEB в зависимости от числа процессов и размера задачи]]&lt;br /&gt;
[[file:Cobwebeff.png|thumb|center|640px|Рис. 3 Эффективность алгоритма COBWEB в зависимости от числа процессов и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
Таким образом можно сделать вывод о том, что данная реализация обладает слабой масштабируемостью. Во многом это связано с высокими накладными расходами на параллелизм в среде исполнения Python.&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Существуют следующие реализации алгоритма COBWEB:&lt;br /&gt;
* [https://github.com/cmaclell/concept_formation/ Concept Formation]&amp;lt;ref name=&amp;quot;gh_cf&amp;quot;&amp;gt;https://github.com/cmaclell/concept_formation/ — библиотека, содержащая реализации алгоритмов COBWEB и COBWEB/3 для языка Python&amp;lt;/ref&amp;gt; библиотека, содержащая реализации алгоритмов COBWEB и COBWEB/3 для языка Python.&lt;br /&gt;
* [http://www.cs.waikato.ac.nz/~ml/weka Weka]&amp;lt;ref&amp;gt;http://www.cs.waikato.ac.nz/~ml/weka — библиотека и инструмент для анализа данных на языке Java&amp;lt;/ref&amp;gt; библиотека и инструмент для анализа данных на языке Java.&lt;br /&gt;
* [http://java-ml.sourceforge.net/ Java-ML] &amp;lt;ref&amp;gt;http://java-ml.sourceforge.net/ — библиотека машинного обучения на языке Java&amp;lt;/ref&amp;gt; библиотека машинного обучения на языке Java.&lt;br /&gt;
&lt;br /&gt;
Так как существуют алгоритмы кластеризации, обладающие лучшими свойствами, алгоритм COBWEB практически не применяется и параллельных реализаций этого алгоритма нет.&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&amp;lt;references&amp;gt;&lt;br /&gt;
&amp;lt;ref name=&amp;quot;wiki&amp;quot;&amp;gt;https://en.wikipedia.org/wiki/Cobweb_(clustering) — описание алгоритма на Википедии (Eng)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;ref name=&amp;quot;habr&amp;quot;&amp;gt;https://habrahabr.ru/post/164417/ — сравнение алгоритма COBWEB с другими алгоритмами кластеризации&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;ref name=&amp;quot;shit&amp;quot;&amp;gt;http://bourabai.ru/tpoi/analysis6.htm — подробное описание алгоритма COBWEB&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;ref name=&amp;quot;paper&amp;quot;&amp;gt;http://www.cl.cam.ac.uk/~av308/cobweb.pdf — статья, в которой алгоритм COBWEB был впервые представлем&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;/references&amp;gt;&lt;/div&gt;</summary>
		<author><name>Dexter</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%A0%D1%83%D1%81%D0%BB%D0%B0%D0%BD&amp;diff=20353</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%A0%D1%83%D1%81%D0%BB%D0%B0%D0%BD&amp;diff=20353"/>
		<updated>2016-12-08T12:24:23Z</updated>

		<summary type="html">&lt;p&gt;Dexter: /* Новые замечания */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Новые замечания ==&lt;br /&gt;
П 1.5 Перечитайте фразу &amp;quot;Алгоритм извлекает все точки в X, которые являются плотность достижима из x и добавляет их в кластер C&amp;quot; - явно что-то не так с грамматикой. Почему x и X в начале этого пункта набраны в виде формул, а затем вдруг стали обычными буквами? Лучше везде использовать формулы &lt;br /&gt;
&lt;br /&gt;
== Замечания к оформлению статьи: ==&lt;br /&gt;
&lt;br /&gt;
0. Укажите свои ФИО, номер группы.&lt;br /&gt;
&lt;br /&gt;
1. В начале статьи должна быть таблица со следующей информацией (Последовательная сложность, Объём входных данных, Объём выходных данных, Высота ярусно-параллельной формы, Ширина ярусно-параллельной формы).&lt;br /&gt;
&lt;br /&gt;
2. В пункте 1.7 должен быть понятный и наглядный рисунок информационного графа (&#039;&#039;&#039;ациклический&#039;&#039;&#039; граф, вершины - операции, дуги - информационные зависимости). (см. пример: https://algowiki-project.org/ru/%D0%A0%D0%B0%D0%B7%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5_%D0%A5%D0%BE%D0%BB%D0%B5%D1%86%D0%BA%D0%BE%D0%B3%D0%BE_(%D0%BC%D0%B5%D1%82%D0%BE%D0%B4_%D0%BA%D0%B2%D0%B0%D0%B4%D1%80%D0%B0%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%BA%D0%BE%D1%80%D0%BD%D1%8F)&lt;br /&gt;
&lt;br /&gt;
3. Вычислительная мощность не приведена. (см. пример: https://algowiki-project.org/ru/%D0%A0%D0%B0%D0%B7%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5_%D0%A5%D0%BE%D0%BB%D0%B5%D1%86%D0%BA%D0%BE%D0%B3%D0%BE_(%D0%BC%D0%B5%D1%82%D0%BE%D0%B4_%D0%BA%D0%B2%D0%B0%D0%B4%D1%80%D0%B0%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%BA%D0%BE%D1%80%D0%BD%D1%8F)&lt;br /&gt;
&lt;br /&gt;
4. В пункте 1.1 не приведено ни одного свойства алгоритма.&lt;br /&gt;
&lt;br /&gt;
5. Пункт 1.3 стоит расписать подробнее. Например, привести основные операции, которые применяются выч. ядре алгоритма. Описать, почему как использование специального вида деревьев улучшает алгоритм.&lt;/div&gt;</summary>
		<author><name>Dexter</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%A0%D1%83%D1%81%D0%BB%D0%B0%D0%BD&amp;diff=20352</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%A0%D1%83%D1%81%D0%BB%D0%B0%D0%BD&amp;diff=20352"/>
		<updated>2016-12-08T12:23:57Z</updated>

		<summary type="html">&lt;p&gt;Dexter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Новые замечания ==&lt;br /&gt;
П 1.5 Перечитайте фразу &amp;quot;Алгоритм извлекает все точки в X, которые являются плотность достижима из x и добавляет их в кластер C&amp;quot; - явно что-то не так с грамматикой. Почему x и X в начале этого пункта набраны в виде формул, а затем вдруг стали обычными буквами? Лучше везде использовать формулы &lt;br /&gt;
&lt;br /&gt;
Замечания к оформлению статьи:&lt;br /&gt;
&lt;br /&gt;
0. Укажите свои ФИО, номер группы.&lt;br /&gt;
&lt;br /&gt;
1. В начале статьи должна быть таблица со следующей информацией (Последовательная сложность, Объём входных данных, Объём выходных данных, Высота ярусно-параллельной формы, Ширина ярусно-параллельной формы).&lt;br /&gt;
&lt;br /&gt;
2. В пункте 1.7 должен быть понятный и наглядный рисунок информационного графа (&#039;&#039;&#039;ациклический&#039;&#039;&#039; граф, вершины - операции, дуги - информационные зависимости). (см. пример: https://algowiki-project.org/ru/%D0%A0%D0%B0%D0%B7%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5_%D0%A5%D0%BE%D0%BB%D0%B5%D1%86%D0%BA%D0%BE%D0%B3%D0%BE_(%D0%BC%D0%B5%D1%82%D0%BE%D0%B4_%D0%BA%D0%B2%D0%B0%D0%B4%D1%80%D0%B0%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%BA%D0%BE%D1%80%D0%BD%D1%8F)&lt;br /&gt;
&lt;br /&gt;
3. Вычислительная мощность не приведена. (см. пример: https://algowiki-project.org/ru/%D0%A0%D0%B0%D0%B7%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5_%D0%A5%D0%BE%D0%BB%D0%B5%D1%86%D0%BA%D0%BE%D0%B3%D0%BE_(%D0%BC%D0%B5%D1%82%D0%BE%D0%B4_%D0%BA%D0%B2%D0%B0%D0%B4%D1%80%D0%B0%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%BA%D0%BE%D1%80%D0%BD%D1%8F)&lt;br /&gt;
&lt;br /&gt;
4. В пункте 1.1 не приведено ни одного свойства алгоритма.&lt;br /&gt;
&lt;br /&gt;
5. Пункт 1.3 стоит расписать подробнее. Например, привести основные операции, которые применяются выч. ядре алгоритма. Описать, почему как использование специального вида деревьев улучшает алгоритм.&lt;/div&gt;</summary>
		<author><name>Dexter</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:MelLain&amp;diff=20351</id>
		<title>Обсуждение участника:MelLain</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:MelLain&amp;diff=20351"/>
		<updated>2016-12-08T12:09:22Z</updated>

		<summary type="html">&lt;p&gt;Dexter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Новые замечания ==&lt;br /&gt;
1) п1.2.2 Что такое n с двойной индексацией? &lt;br /&gt;
&lt;br /&gt;
2) Общие слова о модернизациях - плохой заголовок, переформулируйте &lt;br /&gt;
&lt;br /&gt;
3) п1.5 очень плохое выравнивание в псевдокоде &lt;br /&gt;
&lt;br /&gt;
4) Почему поэлементное умножение вектора на вектор обозначается так же как поэлементное деления вектора на вектор? &lt;br /&gt;
&lt;br /&gt;
== Замечания к [[ЕМ-алгоритм_(Тематическое_моделирование)]] ==&lt;br /&gt;
&lt;br /&gt;
1) следует переоформить пункт 1.5 - или использовать явный псевдокод с отступами в теге &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;
2) отсутствует оценка вычислительной мощности алгоритма в п 1.10&lt;/div&gt;</summary>
		<author><name>Dexter</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:%D0%9A%D0%B0%D0%B7%D0%B0%D0%BA%D0%BE%D0%B2_%D0%90%D1%80%D1%82%D0%B5%D0%BC&amp;diff=19951</id>
		<title>Обсуждение участника:Казаков Артем</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%9E%D0%B1%D1%81%D1%83%D0%B6%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D1%83%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA%D0%B0:%D0%9A%D0%B0%D0%B7%D0%B0%D0%BA%D0%BE%D0%B2_%D0%90%D1%80%D1%82%D0%B5%D0%BC&amp;diff=19951"/>
		<updated>2016-12-02T19:28:32Z</updated>

		<summary type="html">&lt;p&gt;Dexter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Статья [[Участник:Казаков Артем/Алгоритм концептуальной кластеризации COBWEB]] ==&lt;br /&gt;
=== Замечания второго рецензента ===&lt;br /&gt;
* В тексте нет ссылок на источники&lt;br /&gt;
* Сам список оформлен плохо - только гиперссылки. Кроме ссылок нужны названия источников&lt;br /&gt;
* п 1.1 - поясните, что такое концепт&lt;br /&gt;
* п 1.2 - что такое A и B?&lt;br /&gt;
* п 1.3 - список как-то неудачен - соседние пункты - это куски фраз&lt;br /&gt;
=== Замечания по тексту ===&lt;br /&gt;
* В разделе 1.5 кроме псевдокода нужны также текстовые пояснения. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 15:46, 28 ноября 2016 (MSK)&lt;br /&gt;
* Граф, приведённый в разделе 1.7, не является информационным графом (ациклический граф, вершины - операции, дуги - информационные зависимости). [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 15:46, 28 ноября 2016 (MSK)&lt;br /&gt;
** Замечание не исправлено. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 13:17, 30 ноября 2016 (MSK)&lt;br /&gt;
*** Исправил [[Участник:Казаков Артем|Казаков Артем]] ([[Обсуждение участника:Казаков Артем|обсуждение]]) 02:17, 1 декабря 2016 (MSK)&lt;br /&gt;
* В разделе 1.9 должны быть оценки объёмов входных и выходных данных. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 15:46, 28 ноября 2016 (MSK)&lt;br /&gt;
* В разделе 1.10 должна быть оценка вычислительной мощности алгоритма. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 15:46, 28 ноября 2016 (MSK)&lt;br /&gt;
* В разделе 2.4 не приведены все параметры запуска теста - какой компилятор, с какими опциями использовался, какие версии библиотек, на каких узлах проводился запуск и т.д. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 15:46, 28 ноября 2016 (MSK)&lt;br /&gt;
** Замечание не исправлено. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 13:17, 30 ноября 2016 (MSK)&lt;br /&gt;
*** Понятие компилятора и его опций неприменимо для языка Python. Версия интерпретатора была указана (Python 3.5), дополнительных библиотек не использовалось, способ запуска также указан (модель процессора, количество потоков). [[Участник:Казаков Артем|Казаков Артем]] ([[Обсуждение участника:Казаков Артем|обсуждение]]) 02:17, 1 декабря 2016 (MSK)&lt;br /&gt;
* В разделе 2.4 не приведена использованная в экспериментах реализация алгоритма. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 15:46, 28 ноября 2016 (MSK) &lt;br /&gt;
* Из графиков в разделе 2.4 следует сделать выводы о масштабируемости реализации. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 15:46, 28 ноября 2016 (MSK) &lt;br /&gt;
* Рисунки в статье не пронумерованы. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 15:46, 28 ноября 2016 (MSK)&lt;br /&gt;
* В список литературы следует включить ссылки по описываемому алгоритму. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 15:46, 28 ноября 2016 (MSK)&lt;br /&gt;
&lt;br /&gt;
=== Re: Замечания по тексту ===&lt;br /&gt;
Все исправил. [[Участник:Казаков Артем|Казаков Артем]] ([[Обсуждение участника:Казаков Артем|обсуждение]]) 04:57, 30 ноября 2016 (MSK)&lt;/div&gt;</summary>
		<author><name>Dexter</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:Elena777mc/%D0%9F%D0%BB%D0%BE%D1%82%D0%BD%D0%BE%D1%81%D1%82%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_DBSCAN&amp;diff=19368</id>
		<title>Участник:Elena777mc/Плотностный алгоритм кластеризации DBSCAN</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:Elena777mc/%D0%9F%D0%BB%D0%BE%D1%82%D0%BD%D0%BE%D1%81%D1%82%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_DBSCAN&amp;diff=19368"/>
		<updated>2016-11-28T14:59:16Z</updated>

		<summary type="html">&lt;p&gt;Dexter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Преподаватель 1|Dexter}}&lt;br /&gt;
{{Assignment|Sleo}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Плотностный алгоритм кластеризации DBSCAN&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n \log n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(|X| \log |X|)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(m)&amp;lt;/math&amp;gt;&lt;br /&gt;
| 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;
Основные авторы описания: [[Участник:Elena777mc|Малахова Е.С.]] (1.2, 1.4-1.8, 2.4, 2.7), [[Участник:Жаннат_Сагиолданова|Сагиолданова Ж.]] (1.1-1.3, 1.9-1.10, 3)&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация – это процесс разбиения множества с &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; элементами &amp;lt;math&amp;gt;x_1, x_2, ... , x_n (x_n&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; кластеров, так, чтобы в каждом кластере все элементы были схожи&lt;br /&gt;
в каком-то смысле. &amp;lt;math&amp;gt;x_i&amp;lt;/math&amp;gt; могут быть числовыми, категориальными или смешанными данными.  В плотностных методах кластеры рассматриваются как регионы пространства данных с высокой плотностью объектов, которые разделены регионами с низкой плотностью объектов.&lt;br /&gt;
&lt;br /&gt;
Алгоритм DBSCAN (Density Based Spatial Clustering of Applications with Noise) &amp;lt;ref&amp;gt;A density-based algorithm for discovering clusters in large spatial database / M. Ester, H.-P. Kriegel,&lt;br /&gt;
J. Sander, X. Xu // Proc. 1996 Intern. Conf. on Knowledge Discovery and Data Mining. – 1996. – P. 226 –&lt;br /&gt;
231.&amp;lt;/ref&amp;gt; –плотностной алгоритм для кластеризации пространственных данных с присутствием шума, был предложен Мартином Эстер, Гансом-Питером Кригель и их коллегами в 1996 году как решение проблемы разбиения (изначально пространственных) данных на кластеры произвольной формы. &lt;br /&gt;
&lt;br /&gt;
Большинство алгоритмов, производящих плоское разбиение (то есть разбиение объектов на плоскости на непересекающиеся множества/кластеры), создают кластеры по форме близкие к сферическим, так как минимизируют расстояние точки до центра кластера.&lt;br /&gt;
&lt;br /&gt;
Авторы DBSCAN экспериментально показали, что их алгоритм способен распознать кластеры различной формы.&lt;br /&gt;
Идея, положенная в основу алгоритма, заключается в том, что внутри каждого кластера плотность точек (объектов) заметно выше, чем плотность снаружи кластера, а также плотность в областях с шумом ниже плотности любого из кластеров. Еще точнее, для каждой точки кластера ее окрестность в диапазоне заданного радиуса должна содержать не менее некоторого числа точек, которое задается пороговым значением.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
[[File:Dbscan_picture.png|thumb|right|500px| Рис. 1. Пример ядровых, граничных и шумовых точек алгоритма. Точка A - ядровая, точки  B и С - граничные, N - шум. В данном примере MinPts = 4, Eps равен радиусу окружности &amp;lt;ref&amp;gt;https://upload.wikimedia.org/wikipedia/commons/thumb/a/af/DBSCAN-Illustration.svg/400px-DBSCAN-Illustration.svg.png&amp;lt;/ref&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Исходные данные: объекты, которые нужно кластеризовать, параметры &amp;lt;math&amp;gt;MinPts, \  \varepsilon&amp;lt;/math&amp;gt; . Между объектами можно считать расстояния.&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные: разбиение объектов по кластерам. Количество кластеров зависит от исходных данных.  &amp;lt;ref&amp;gt;&amp;quot;Xu, X. A fast parallel clustering algorithm for large spatial databases / X. Xu, M. Ester, H.-P. Kriegel // Proc. 1999 Intern. Conf. on Knowledge Discovery and Data Mining. – 1999. – Vol. 3, is. 3. – P. 263 – 290.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для построения оценки плотности, на основе соседства точек вводятся понятия&lt;br /&gt;
достижимости и связности. Под &amp;lt;math&amp;gt;\varepsilon &amp;lt;/math&amp;gt; -соседями точки &amp;lt;math&amp;gt;x \in X&amp;lt;/math&amp;gt; понимается множество точек, расстояние до которых не превышает &amp;lt;math&amp;gt;\varepsilon &amp;lt;/math&amp;gt;, т. е.&lt;br /&gt;
 &amp;lt;math&amp;gt;N_\varepsilon (x) = \{y \in X | D(x, y) \le \varepsilon\}&amp;lt;/math&amp;gt;.&lt;br /&gt;
Тогда точка &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; достижима из точки &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;, если существует последовательность точек &amp;lt;math&amp;gt;x^{(1)}=x, x^{(2)},... , x^{(p-1)}, x^{(p)}=y&amp;lt;/math&amp;gt;, для которой выполнено:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  \begin{align}&lt;br /&gt;
x^{(i+1)} \in N_\varepsilon (x^{(i)}), i=1,... ,p-1 \\&lt;br /&gt;
\mid  N_\varepsilon (x^{(i)}) \mid \ge MinPts, i=1,... ,p-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;MinPts&amp;lt;/math&amp;gt; задаётся пользователем и регулирует порог «шума». Согласно второму условию, у точек, находящихся внутри кластера, должно быть не менее &amp;lt;math&amp;gt;MinPts \   \varepsilon&amp;lt;/math&amp;gt; -соседей. Такие точки называются «ядрами». Остальные точки разделяются на граничные (имеющие менее &amp;lt;math&amp;gt;MinPts \   \varepsilon &amp;lt;/math&amp;gt; -cоседей, но достижимые из какого-либо «ядра») и шумовые. Две точки связны, если существует «ядро», из которого они обе достижимы.&lt;br /&gt;
При такой постановке задачи, под кластером понимается максимальное связное подмножество множества &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; . Точки, не попавшие в какой-либо кластер (не принадлежащие &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; -окрестности какого-либо «ядра»), относятся к классу «шум».&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром алгоритма является нахождение &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;-соседей каждого объекта входного множества &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt;. На эту часть алгоритма приходится основное время работы алгоритма, так как требуется найти всех соседей для каждого объекта заданного множества. Основные операции, которые применяются в вычислительном ядре  алгоритма: нахождение расстояние между объектами и сравнение расстояния с порогом для определения того, являются ли данные объекты &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;-соседями.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма == &lt;br /&gt;
Алгоритм DBSCAN использует пространственную структуру данных для определения соседних объектов. Такие структуры данных позволяют найти все объекты в пределах определенного расстояния от текущего объекта. Сложность построения таких структур &amp;lt;math&amp;gt;O(n \log n)&amp;lt;/math&amp;gt;, и использование такой структуры не увеличит сложность всего алгоритма (если сложность самого алгоритма &amp;lt;math&amp;gt;O(n \log n)&amp;lt;/math&amp;gt;). Также для построения таких деревьев нужно уметь находить расстояния между объектами &amp;lt;math&amp;gt;\rho(u,v)&amp;lt;/math&amp;gt;, это расстояние можно вводить разными способами. Например, если &amp;lt;math&amp;gt;\rho(u,v)&amp;lt;/math&amp;gt; - метрика в евклидовом пространстве, &amp;lt;math&amp;gt;u=(u_1,...,u_n)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(v_1,...,v_n)&amp;lt;/math&amp;gt;, то расстояние вычисляется следующим образом: &amp;lt;math&amp;gt;\rho(u,v)=\sqrt{(u_1-v_1)^2+(u_2-v_2)^2+...+(u_n-v_n)^2} = \sqrt{\sum_{k=1}^n(u_k-v_k)^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Последовательная реализация алгоритма может быть представлена следующим псевдокодом:&lt;br /&gt;
&lt;br /&gt;
 // Основная функция, которая реализует алгоритм кластеризации&lt;br /&gt;
 &amp;lt;math&amp;gt;DBSCAN(X, \varepsilon, MinPts)&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;FORALL&amp;lt;/math&amp;gt;  objects  &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; in &amp;lt;math&amp;gt;X\  DO&amp;lt;/math&amp;gt;&lt;br /&gt;
       &amp;lt;math&amp;gt;IF\  x&amp;lt;/math&amp;gt; is unclassified&lt;br /&gt;
         call function &amp;lt;math&amp;gt;expand\_cluster&amp;lt;/math&amp;gt; to construct a cluster wrt. &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; and &amp;lt;math&amp;gt;MinPts&amp;lt;/math&amp;gt; containing &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 // Функция, которая строит кластер на основе одной точки&lt;br /&gt;
 &amp;lt;math&amp;gt;FUNCTION\ expand\_cluster(x,X,\varepsilon, MinPts):&amp;lt;/math&amp;gt;&lt;br /&gt;
    &amp;lt;math&amp;gt;retrive\_\varepsilon neighborhood(x, \varepsilon)&amp;lt;/math&amp;gt;;&lt;br /&gt;
    &amp;lt;math&amp;gt;IF \mid N_{\varepsilon}(x) \mid &amp;lt; MinPts&amp;lt;/math&amp;gt; //т.е. &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; - объект, не являющийся ядром&lt;br /&gt;
       mark &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; as &amp;lt;math&amp;gt;noise&amp;lt;/math&amp;gt;  and &amp;lt;math&amp;gt;RETURN&amp;lt;/math&amp;gt;;&lt;br /&gt;
    &amp;lt;math&amp;gt;ELSE&amp;lt;/math&amp;gt;//т.е. &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; - объект, являющийся ядром&lt;br /&gt;
       select a new cluster-id and mark all objects in &amp;lt;math&amp;gt;N_{\varepsilon}(x)&amp;lt;/math&amp;gt; with this current &amp;lt;math&amp;gt;cluster-id&amp;lt;/math&amp;gt;; &lt;br /&gt;
       push all objects from &amp;lt;math&amp;gt;N_{\varepsilon}(x)&amp;lt;/math&amp;gt;\&amp;lt;math&amp;gt;(x)&amp;lt;/math&amp;gt; onto the stack seeds;&lt;br /&gt;
       &amp;lt;math&amp;gt;WHILE\ NOT&amp;lt;/math&amp;gt; seeds.empty() &amp;lt;math&amp;gt;DO&amp;lt;/math&amp;gt; &lt;br /&gt;
         &amp;lt;math&amp;gt;currentObject&amp;lt;/math&amp;gt; := seeds.top();&lt;br /&gt;
         seeds.pop();&lt;br /&gt;
         &amp;lt;math&amp;gt;retrive\_\varepsilon neighborhood(currentObject, \varepsilon)&amp;lt;/math&amp;gt;;&lt;br /&gt;
         &amp;lt;math&amp;gt;IF \mid N_{\varepsilon}(currentObjects) \mid \ge MinPts&amp;lt;/math&amp;gt;&lt;br /&gt;
           select all objects in &amp;lt;math&amp;gt;N_{\varepsilon}(currentObject)&amp;lt;/math&amp;gt; not yet classified or marked as &amp;lt;math&amp;gt;noise&amp;lt;/math&amp;gt;,&lt;br /&gt;
           push the unclassified objects onto seeds and mark all of these objects with current &amp;lt;math&amp;gt;cluster-id&amp;lt;/math&amp;gt;;&lt;br /&gt;
     &amp;lt;math&amp;gt;RETURN&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 // Функция, для определения &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;-соседей для объекта&lt;br /&gt;
 &amp;lt;math&amp;gt;FUNCTION\ retrive\_\varepsilon neighborhood(x, \varepsilon)&amp;lt;/math&amp;gt; //функция возвращает соседей на основе пространственной структуры данных&lt;br /&gt;
   return &amp;lt;math&amp;gt;\{ x&#039; \ | \ \forall x&#039; \in X: \rho(x, x&#039;) &amp;lt; \varepsilon \}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Для того, чтобы алгоритм мог кластеризовать все объекты, необходимо пройти по каждому из них хотя бы один раз. Если использовать R*-дерево или kd-дерево для определения соседних объектов со сложностью &amp;lt;math&amp;gt;O(\log n)&amp;lt;/math&amp;gt;, то сложность алгоритма &amp;lt;math&amp;gt;O(n \log 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;
[[File:Dbscan_schema.jpg|1000px|thumb|center|Рис.1. Общая информационная структура алгоритма]]&lt;br /&gt;
Разбиение данных происходит с помощью пространственной структуры данных (R*-дерево, kd-дерево), которая разбивает все множество объектов &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; на &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; частей: &amp;lt;math&amp;gt;X_1,X_2,...,X_m&amp;lt;/math&amp;gt;.&lt;br /&gt;
На каждой части объектов применяется алгоритм PDBSCAN. PDBSCAN - это последовательный алгоритм DBSCAN, применяемый только к одной части объектов, и для каждой из этих частей он определяет кандидатов на слияние. PDBSCAN использует пространственную структуру, которая распределяется вместе с данными.&lt;br /&gt;
Если для ядрового объекта части &amp;lt;math&amp;gt;X_i&amp;lt;/math&amp;gt; в &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;-окрестности находится объект из другой части &amp;lt;math&amp;gt;X_j&amp;lt;/math&amp;gt;, то такие объекты становятся кандидатами на слияние. &lt;br /&gt;
&lt;br /&gt;
Само слияние осуществляется следующим образом: для каждой пары кандидатов на слияние, объединяем кластеры, соответствующие этим кандидатам в один общий кластер.&lt;br /&gt;
&lt;br /&gt;
[[File:dbscan_clusters_partitions.png|500px|thumb|center|Рис.2. Пример разбиения объектов на части на основе пространственной структуры. Каждый прямоугольник соответствует части данных, каждая из которых подается на вход алгоритму PDBSCAN &amp;lt;ref&amp;gt;https://github.com/bwoneill/pypardis/blob/master/plots/median_search_split/clusters_partitions.png&amp;lt;/ref&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Как видно из общей структуры графа алгоритма, ширина ярусно-параллельной формы алгоритма &amp;lt;math&amp;gt;O(m)&amp;lt;/math&amp;gt;, где m - количество частей, на которые разбиваются все входное множество объектов &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt;. Высотой ярусно-параллельной формы алгоритма является &amp;lt;math&amp;gt;O(|X| \log |X|)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\mid X \mid&amp;lt;/math&amp;gt; - максимальное количество среди числа объектов в каждой части разбиения. Именно такую сложность имеет алгоритм PDBSCAN, применяемый к каждой отдельной части разбиения.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: множество точек X из n-мерного пространства, на котором определена функция расстояния D. В наиболее распространенном случае пространственной кластеризации используется Евлидова метрика между векторами из &amp;lt;math&amp;gt;{R}^n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: n (размерность входящего множества)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: размеченное множество точек X, в котором каждой точке соответствует номер ее кластера. Обычно каждой точке из X сопоставляется ее номер, а на выходе алгоритм дает отображение номеров точек в номера соответствующих им кластеров, например в виде вектора размера |X|&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: n (размерность выходящего множества)&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;
* параллельная реализация сбалансирована по количеству и виду производимых операций (вычисление расстояния, сравнение с &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;);&lt;br /&gt;
* не требуется задание числа кластеров;&lt;br /&gt;
* может выделять кластеры в присутствии «шума»и выбросов &amp;lt;ref&amp;gt;АЛГОРИТМЫ КЛАСТЕРИЗАЦИИ В ЗАДАЧАХ СЕГМЕНТАЦИИ&lt;br /&gt;
СПУТНИКОВЫХ ИЗОБРАЖЕНИЙ/ И. А. Пестунов, Ю. Н. Синявский// Вестник Кемеровского государственного университета. – 2012. – P. 263–&lt;br /&gt;
299.&amp;lt;/ref&amp;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;
* не детерминирован, так как граничные точки, достижимые из более, чем одного кластера, могут быть частью любого из них в зависимости от порядка обрабатываемых данных. Однако такая ситуация возникает редко, а относительно ядровых точек и шума DBSCAN детерминирован.&lt;br /&gt;
* плохо работает на кластерах, которые имеют небольшое пересечение между собой.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Было проведено исследование масштабируемости параллельной реализации алгоритма DBSCAN . Исследование проводилось на суперкомпьютере &amp;quot;Ломоносов&amp;quot; [http://parallel.ru/cluster Суперкомпьютерного комплекса Московского университета]. Исследовалась параллельная реализация алгоритма, написанная с использованием стандарта MPI. Распараллеливание проводилось по числу входных объектов, поэтому исследование масштабируемости проводилось для числа входных объектов.  Алгоритм тестировался на известном датасете для кластеризации: [https://archive.ics.uci.edu/ml/datasets/Individual+household+electric+power+consumption Machine Learning Repository]&lt;br /&gt;
&lt;br /&gt;
Набор и границы значений изменяемых [[Глоссарий#Параметры запуска|параметров запуска]] реализации алгоритма: &lt;br /&gt;
&lt;br /&gt;
*	число процессоров [1 : 128] с шагом по степеням двойки;&lt;br /&gt;
*	число входных объектов [1000 : 40000].&lt;br /&gt;
&lt;br /&gt;
На следующих рисунках приведены графики производительности и эффективности распараллеливания алгоритма DBSCAN в зависимости от изменяемых параметров запуска.&lt;br /&gt;
[[File:Dbscan_perfomance.png|800px|thumb|center|Рис.1. Изменение производительности в зависимости от числа процессов и числа входных данных]]&lt;br /&gt;
[[File:Dbscan_efficiency.png|800px|thumb|center|Рис.2. Изменение эффективности распараллеливания в зависимости от числа процессов и числа входных данных]]&lt;br /&gt;
&lt;br /&gt;
Построим оценки масштабируемости протестированной параллельной реализации алгоритма DBSCAN: &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;По числу процессов&#039;&#039;&#039; - при увеличении числа процессов наблюдается уменьшение эффективности на всей области рассматриваемых значений параметров. При этом с ростом числа процессов снижение эффективности замедляется. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;По размеру задачи&#039;&#039;&#039; - При увеличении размерности системы при фиксированном количестве процессов на области изменений значений параметров наблюдается увеличение эффективности. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;При одновременном увеличении количества процессов и размерности системы&#039;&#039;&#039; наблюдается уменьшение эффективности. При этом скорость убывания эффективности крайне низкая.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/elena777mc/dbscan/tree/master Исследованная параллельная реализация на языке C++]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* [http://scikit-learn.org/stable/modules/generated/sklearn.cluster.DBSCAN.html Scikit learn (Python, последовательная реализация)]&lt;br /&gt;
* [http://cucis.ece.northwestern.edu/projects/Clustering/download_code_dbscan.html Northwestern University (C++, параллельная реализация kd-tree)]&lt;br /&gt;
* [https://github.com/ContinuumIO/parallel_dbscan github/ContinuumIO (Python, параллельная реализация)]&lt;br /&gt;
* [https://github.com/propanoid/DBSCAN github/propanoid (C++, последовательная реализация VP tree)]&lt;br /&gt;
* [https://github.com/dparks1134/DBSCAN github/dparks1134 (С++, последовательная реализация)]&lt;br /&gt;
* [https://github.com/ahbarnett/validspike/tree/master/contrib/dbscan_patwary Disjoint-Set Data Structure based Parallel DBSCAN (C++ параллельная реализация kd-tree)]&lt;br /&gt;
* [https://github.com/bwoneill/pypardis github/bwoneill (Spark/Python параллельная реализация kd-tree)]&lt;br /&gt;
* [https://github.com/alitouka/spark_dbscan github/alitouka (Spark/Scala параллельная реализация)]&lt;br /&gt;
* [https://github.com/mhahsler/dbscan CRAN (R, последовательная реализация)]&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;br /&gt;
&amp;lt;references \&amp;gt;[https://pdfs.semanticscholar.org/a3f8/a3948e5999def4a0819d0dbaef2ae05e1599.pdf (A Fast Parallel Clustering Algorithm for Large Spatial Databases, JOCHEN JAGER, HANS-PETER KRIEGEL)]&lt;br /&gt;
&amp;lt;references \&amp;gt;[http://cyberleninka.ru/article/n/algoritmy-klasterizatsii-v-zadachah-segmentatsii-sputnikovyh-izobrazheniy (АЛГОРИТМЫ КЛАСТЕРИЗАЦИИ В ЗАДАЧАХ СЕГМЕНТАЦИИ СПУТНИКОВЫХ ИЗОБРАЖЕНИЙ, Пестунов Игорь Алексеевич, Синявский Юрий Николаевич)]&lt;br /&gt;
&lt;br /&gt;
[[en:Cholesky decomposition]]&lt;br /&gt;
&lt;br /&gt;
[[Категория:Законченные статьи]]&lt;/div&gt;</summary>
		<author><name>Dexter</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:Elmon/%D0%9F%D0%BB%D0%BE%D1%82%D0%BD%D0%BE%D1%81%D1%82%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_DBSCAN&amp;diff=19367</id>
		<title>Участник:Elmon/Плотностный алгоритм кластеризации DBSCAN</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:Elmon/%D0%9F%D0%BB%D0%BE%D1%82%D0%BD%D0%BE%D1%81%D1%82%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_DBSCAN&amp;diff=19367"/>
		<updated>2016-11-28T14:58:14Z</updated>

		<summary type="html">&lt;p&gt;Dexter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Преподаватель 1|Dexter}}&lt;br /&gt;
{{Assignment|Sleo}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Плотностный алгоритм кластеризации DBSCAN&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n \log n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(|H| \log |H|)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(w)&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;
Основной автор описания: [[User:Elmon|Гилевич В.В.]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация — это процедура, упорядочивающая элементы из некоторого множества в сравнительно однородные группы (кластеры). Элементы могут содержать числовые, категориальные или смешанные данные. Плотностные методы выделяют кластеры на основе следующей идеи: кластером считается регион с высокой плотностью объектов, которые разделены разреженными регионами (с низкой плотностью объектов)&lt;br /&gt;
&lt;br /&gt;
Алгоритм DBSCAN (Density Based Spatial Clustering of Applications with Noise) &amp;lt;ref&amp;gt;A density-based algorithm for discovering clusters in large spatial database / M. Ester, H.-P. Kriegel,&lt;br /&gt;
J. Sander, X. Xu // Proc. 1996 Intern. Conf. on Knowledge Discovery and Data Mining. – 1996.&amp;lt;/ref&amp;gt; — плотностной алгоритм для кластеризации пространственных данных с присутствием шума, был предложен Мартином Эстер, Гансом-Питером Кригель и их коллегами в 1996 году как решение проблемы разбиения данных на кластеры произвольной формы.&lt;br /&gt;
&lt;br /&gt;
Алгоритм имеет ряд отличительных свойств:&lt;br /&gt;
* Не требуется заранее определять число кластеров&lt;br /&gt;
* Может отличать кластеры, которые нельзя разделить прямой линией (плоскостью, для N-мерного пространства), в том числе кластера, частично или полностью окруженные другим кластером.&lt;br /&gt;
* Хорошо работает в условиях зашумленных входных данных&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Исходные данные ===&lt;br /&gt;
Множество &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt;, на котором определена функция расстояния &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
=== Вычисляемые данные===&lt;br /&gt;
Множество пар из элемента множества &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt;, и соответствующий ему номер кластера.&lt;br /&gt;
&lt;br /&gt;
=== Параметры алгоритма ===&lt;br /&gt;
* &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; — максимальное расстояние между соседями;&lt;br /&gt;
* &amp;lt;math&amp;gt;MinPts&amp;lt;/math&amp;gt; — минимальное количество элементов находящихся &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;-окрестности данного элемента для создания кластера.&lt;br /&gt;
&lt;br /&gt;
=== Определения ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;ядровой элемент&#039;&#039;: элемент &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; является ядровым, если количество элементов в &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;-окрестности, включая сам элемент &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; больше или равно &amp;lt;math&amp;gt;MinPts&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;достижимость напрямую элемента &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; из элемента q&#039;&#039;: элемент &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; считается достижимым напрямую из элемента &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt;, если элемент &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; является ядровым, а элемент &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; находится в &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;-окрестности элемента q;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;достижимость элемента &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; из элемента &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt;&#039;&#039;: элемент &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; достижим из элемента &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt;, если существует путь &amp;lt;math&amp;gt;p_1, \dots, p_n&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;p_1 = p&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;p_n = q&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;p_{i + 1}&amp;lt;/math&amp;gt; напрямую достижим из &amp;lt;math&amp;gt;p_{i}&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;шум&#039;&#039;: все элементы, недостижимые из какого-либо другого считаются шумом.&lt;br /&gt;
&lt;br /&gt;
Так как достижимость не является симметричным отношением (никакой элемент не может быть достижим из неядрового, вне зависимости от расстояния), то предлагается ввести следующее отношение:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;связанность элемента p и элемента q&#039;&#039;: элемент &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; считается связанным с &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt;, если существует такой элемент &amp;lt;math&amp;gt;o&amp;lt;/math&amp;gt;, что &amp;lt;math&amp;gt;p&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; должен удовлетворять двум условиям:&lt;br /&gt;
* Все элементы внутри кластера взаимно связанны;&lt;br /&gt;
* Если элемент связан с каким-либо элементом кластера, то он тоже является частью кластера.&lt;br /&gt;
&lt;br /&gt;
[[File:DBSCAN-Illustration.svg|thumb|right|400px| Рис. 1. Для &#039;&#039;MinPts&#039;&#039; = 4. Красные элементы соответствуют ядровым, желтые — достижимым, синяя — шуму.&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/DBSCAN Density-based spatial clustering of applications with noise (DBSCAN)&amp;lt;/ref&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
=== Пошаговое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
#Выбирается произвольная непосещенный элемент &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;.&lt;br /&gt;
#Элемент &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; помечается как посещенный. &lt;br /&gt;
#Проверяется, является ли элемент &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; ядровым.&lt;br /&gt;
#*Если элемент &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; является ядровым, то: &lt;br /&gt;
#**Он становится началом нового кластера или сохраняет номер кластера, который был присвоен элементу ранее; &lt;br /&gt;
#**Все элементы из &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;-окрестности элемента &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; добавляются в его кластер (им присваевается номер кластера элемента &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;);&lt;br /&gt;
#**Процесс продолжается рекурсивно для каждого непосещенного элемента текущего кластера c шага 2.&lt;br /&gt;
#*Если элемент &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; не является ядровым, то &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; объявляется шумом. Алгоритм продолжается с шага 4.&lt;br /&gt;
#Если остались непосещенные точки, то алгоритм продолжается с шага 1.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром алгоритма является поиск элементов в &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;-окрестности каждого элемента входного множества &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt;. На эту часть алгоритма приходится основное время работы алгоритма, так как для каждого элемента необходимо выполнить эту операцию. Основные операции вычислительного ядра алгоритма: нахождение расстояние между элементами множества и сравнение его с порогом для определения того, являются ли один элемент достижимым напрямую из другого.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма == &lt;br /&gt;
&lt;br /&gt;
Алгоритм DBSCAN предполагает использование пространственной структуры данных (структуры, ориентированной на индексацию многомерной информации, такой как географические данные) — такие структуры позволяют найти все элементы в пределах определенного расстояния от текущего за &amp;lt;math&amp;gt;O(\log n)&amp;lt;/math&amp;gt;. Сложность построения таких структур &amp;lt;math&amp;gt;O(n \log n)&amp;lt;/math&amp;gt;, таким образом, использование такой структуры не увеличивает сложность всего алгоритма.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;DBSCAN(X, \varepsilon, MinPts)&amp;lt;/math&amp;gt;&lt;br /&gt;
   &amp;lt;math&amp;gt;C = 0&amp;lt;/math&amp;gt;&lt;br /&gt;
   for &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; in &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt;:&lt;br /&gt;
     if &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; is &amp;lt;math&amp;gt;visited&amp;lt;/math&amp;gt;:&lt;br /&gt;
       # Skipping already visited elements&lt;br /&gt;
       continue&lt;br /&gt;
     mark &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; as &amp;lt;math&amp;gt;visited&amp;lt;/math&amp;gt;&lt;br /&gt;
     # [Core operation] Searching for neighbors&lt;br /&gt;
     &amp;lt;math&amp;gt;neighbours&amp;lt;/math&amp;gt; = &amp;lt;math&amp;gt;\{ o \ | \ \forall o \in X: D(p, o) \le \varepsilon \}&amp;lt;/math&amp;gt;&lt;br /&gt;
     if &amp;lt;math&amp;gt;| neighbours | \ge MinPts&amp;lt;/math&amp;gt;:&lt;br /&gt;
       # Found new cluster&lt;br /&gt;
       &amp;lt;math&amp;gt;C = C + 1&amp;lt;/math&amp;gt;&lt;br /&gt;
       add &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; to cluster &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&lt;br /&gt;
       # Looking for more neighbors, until none left&lt;br /&gt;
       for &amp;lt;math&amp;gt;q \in neighbours&amp;lt;/math&amp;gt;:&lt;br /&gt;
         if &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; is not &amp;lt;math&amp;gt;visited&amp;lt;/math&amp;gt;:&lt;br /&gt;
           # If element is visited, then either it was marked as part of other cluster, or as noise&lt;br /&gt;
           mark &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; as &amp;lt;math&amp;gt;visited&amp;lt;/math&amp;gt;&lt;br /&gt;
           # [Core operation] Searching for neighbors&lt;br /&gt;
           &amp;lt;math&amp;gt;q\_neighbours&amp;lt;/math&amp;gt; = &amp;lt;math&amp;gt;\{ o \ | \ \forall o \in X: D(q, o) \le \varepsilon \}&amp;lt;/math&amp;gt;&lt;br /&gt;
           if &amp;lt;math&amp;gt;| q\_neighbours | \ge MinPts&amp;lt;/math&amp;gt;:&lt;br /&gt;
             # We can expand neighbors with new elements from element &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt;&lt;br /&gt;
             &amp;lt;math&amp;gt;neighbours&amp;lt;/math&amp;gt; = &amp;lt;math&amp;gt;neighbours \cup q\_neighbours&amp;lt;/math&amp;gt;  &lt;br /&gt;
         if &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; has no cluster mark:&lt;br /&gt;
           # If it&#039;s noise — mark as edge-element part of cluster&lt;br /&gt;
           mark &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; as part of cluster &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&lt;br /&gt;
     else:&lt;br /&gt;
       mark &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; as &amp;lt;math&amp;gt;noise&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Для того, чтобы проверить принадлежность элемента множества к кластеру необходимо получить список соседей в его &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;-окрестности. При использовании пространственной структуры данных данная операция может быть выполнена со сложностью &amp;lt;math&amp;gt;O(\log n)&amp;lt;/math&amp;gt;. Так как для необходимо определить принадлежность к кластеру всех элементов множества, то сложность самого алгоритма &amp;lt;math&amp;gt;O(n \log n)&amp;lt;/math&amp;gt;. При отказе от использования таких сткрутр сложность возрастает до &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt;, так как для каждого элемента требуется проверить на нахождение в &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;-окрестности все остальные элементы множества.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
Опишем граф алгоритма как аналитически, так и в виде рисунка:&lt;br /&gt;
&lt;br /&gt;
Граф алгоритма состоит из двух групп вершин, расположенных узлах двух областей двумерной размерности.&lt;br /&gt;
&lt;br /&gt;
Первой группе вершин соответствует операция Neighbours. Естественно введённые координаты области таковы:&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;k + f&amp;lt;/math&amp;gt;, принимая все целочисленные значения, где &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; — число результирующих кластеров, &amp;lt;math&amp;gt;f&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;t&amp;lt;/math&amp;gt;, принимая все целочисленные значения, где &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; — число вершин в кластере &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;&lt;br /&gt;
Второй группе вершин соответствует операция Check. Естественно введённые координаты области аналогичны предыдущей.&lt;br /&gt;
&lt;br /&gt;
[[File:DBSCAN algo graph.png|thumb|center|800px|Рис. 2. Граф алгоритма DBSCAN с отображением входных данных. Element — входные данные, Neighbours —  операция поиска соседей, Check — операция проверки условий, добавления вершины к кластеру и выбора новой, Out — результаты.]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Так как в данном алгоритме присутствует параллелизм по данным, ширина ярусно-параллельной формы алгоритма &amp;lt;math&amp;gt;O(w)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;w&amp;lt;/math&amp;gt; — количество частей, на которые разбиваются все входное множество объектов &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt;. Высотой ярусно-параллельной формы алгоритма является &amp;lt;math&amp;gt;O(|H| \log |H|)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;|H|&amp;lt;/math&amp;gt; — максимальное количество элементов в области среди всех частей разбиения. Именно такую сложность имеет алгоритм PDBSCAN&amp;lt;ref&amp;gt;[http://www.ece.northwestern.edu/~choudhar/Publications/ANewScalableParallelDBSCANAlgorithmUsingDisjointSetDataStructure.pdf A New Scalable Parallel DBSCAN Algorithm Using the Disjoint-Set Data Structure \ Md. Mostofa Ali Patwary, Diana Palsetia, Ankit Agrawal, Wei-keng Liao, Fredrik Manne, Alok Choudhary]&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&amp;lt;/math&amp;gt;, на котором определена функция расстояния &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: &amp;lt;math&amp;gt;n&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;, в котором каждому элементу соответствует номер его кластера.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: &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;
* Не детерминирован относительно граничных точек кластеров.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/ContinuumIO/parallel_dbscan Параллельная реализация для Python на OpenMP/MPI]&lt;br /&gt;
* [https://github.com/propanoid/DBSCAN Параллельная реализация для C++ на Boost и OpenMP с использованием VP-дерева]&lt;br /&gt;
* [https://github.com/ahbarnett/validspike/tree/master/contrib/dbscan_patwary Параллельная реализация для С++ на OpenMP с использованием системы непересекающихся множеств]&lt;br /&gt;
* [https://github.com/bwoneill/pypardis Параллельная реализация для многомерных данных для Python на SciPy и NumPy ]&lt;br /&gt;
* [https://github.com/mhahsler/dbscan Последовательная реализация для R на С++]&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[en:DBSCAN]]&lt;/div&gt;</summary>
		<author><name>Dexter</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:Elena777mc/%D0%9F%D0%BB%D0%BE%D1%82%D0%BD%D0%BE%D1%81%D1%82%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_DBSCAN&amp;diff=19366</id>
		<title>Участник:Elena777mc/Плотностный алгоритм кластеризации DBSCAN</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:Elena777mc/%D0%9F%D0%BB%D0%BE%D1%82%D0%BD%D0%BE%D1%81%D1%82%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_DBSCAN&amp;diff=19366"/>
		<updated>2016-11-28T14:57:52Z</updated>

		<summary type="html">&lt;p&gt;Dexter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Преподаватель 1|Dexter}}&lt;br /&gt;
{Assignment|Sleo}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Плотностный алгоритм кластеризации DBSCAN&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n \log n)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(|X| \log |X|)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(m)&amp;lt;/math&amp;gt;&lt;br /&gt;
| 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;
Основные авторы описания: [[Участник:Elena777mc|Малахова Е.С.]] (1.2, 1.4-1.8, 2.4, 2.7), [[Участник:Жаннат_Сагиолданова|Сагиолданова Ж.]] (1.1-1.3, 1.9-1.10, 3)&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
Кластеризация – это процесс разбиения множества с &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; элементами &amp;lt;math&amp;gt;x_1, x_2, ... , x_n (x_n&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; кластеров, так, чтобы в каждом кластере все элементы были схожи&lt;br /&gt;
в каком-то смысле. &amp;lt;math&amp;gt;x_i&amp;lt;/math&amp;gt; могут быть числовыми, категориальными или смешанными данными.  В плотностных методах кластеры рассматриваются как регионы пространства данных с высокой плотностью объектов, которые разделены регионами с низкой плотностью объектов.&lt;br /&gt;
&lt;br /&gt;
Алгоритм DBSCAN (Density Based Spatial Clustering of Applications with Noise) &amp;lt;ref&amp;gt;A density-based algorithm for discovering clusters in large spatial database / M. Ester, H.-P. Kriegel,&lt;br /&gt;
J. Sander, X. Xu // Proc. 1996 Intern. Conf. on Knowledge Discovery and Data Mining. – 1996. – P. 226 –&lt;br /&gt;
231.&amp;lt;/ref&amp;gt; –плотностной алгоритм для кластеризации пространственных данных с присутствием шума, был предложен Мартином Эстер, Гансом-Питером Кригель и их коллегами в 1996 году как решение проблемы разбиения (изначально пространственных) данных на кластеры произвольной формы. &lt;br /&gt;
&lt;br /&gt;
Большинство алгоритмов, производящих плоское разбиение (то есть разбиение объектов на плоскости на непересекающиеся множества/кластеры), создают кластеры по форме близкие к сферическим, так как минимизируют расстояние точки до центра кластера.&lt;br /&gt;
&lt;br /&gt;
Авторы DBSCAN экспериментально показали, что их алгоритм способен распознать кластеры различной формы.&lt;br /&gt;
Идея, положенная в основу алгоритма, заключается в том, что внутри каждого кластера плотность точек (объектов) заметно выше, чем плотность снаружи кластера, а также плотность в областях с шумом ниже плотности любого из кластеров. Еще точнее, для каждой точки кластера ее окрестность в диапазоне заданного радиуса должна содержать не менее некоторого числа точек, которое задается пороговым значением.&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
[[File:Dbscan_picture.png|thumb|right|500px| Рис. 1. Пример ядровых, граничных и шумовых точек алгоритма. Точка A - ядровая, точки  B и С - граничные, N - шум. В данном примере MinPts = 4, Eps равен радиусу окружности &amp;lt;ref&amp;gt;https://upload.wikimedia.org/wikipedia/commons/thumb/a/af/DBSCAN-Illustration.svg/400px-DBSCAN-Illustration.svg.png&amp;lt;/ref&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Исходные данные: объекты, которые нужно кластеризовать, параметры &amp;lt;math&amp;gt;MinPts, \  \varepsilon&amp;lt;/math&amp;gt; . Между объектами можно считать расстояния.&lt;br /&gt;
&lt;br /&gt;
Вычисляемые данные: разбиение объектов по кластерам. Количество кластеров зависит от исходных данных.  &amp;lt;ref&amp;gt;&amp;quot;Xu, X. A fast parallel clustering algorithm for large spatial databases / X. Xu, M. Ester, H.-P. Kriegel // Proc. 1999 Intern. Conf. on Knowledge Discovery and Data Mining. – 1999. – Vol. 3, is. 3. – P. 263 – 290.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для построения оценки плотности, на основе соседства точек вводятся понятия&lt;br /&gt;
достижимости и связности. Под &amp;lt;math&amp;gt;\varepsilon &amp;lt;/math&amp;gt; -соседями точки &amp;lt;math&amp;gt;x \in X&amp;lt;/math&amp;gt; понимается множество точек, расстояние до которых не превышает &amp;lt;math&amp;gt;\varepsilon &amp;lt;/math&amp;gt;, т. е.&lt;br /&gt;
 &amp;lt;math&amp;gt;N_\varepsilon (x) = \{y \in X | D(x, y) \le \varepsilon\}&amp;lt;/math&amp;gt;.&lt;br /&gt;
Тогда точка &amp;lt;math&amp;gt;y&amp;lt;/math&amp;gt; достижима из точки &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;, если существует последовательность точек &amp;lt;math&amp;gt;x^{(1)}=x, x^{(2)},... , x^{(p-1)}, x^{(p)}=y&amp;lt;/math&amp;gt;, для которой выполнено:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
  \begin{align}&lt;br /&gt;
x^{(i+1)} \in N_\varepsilon (x^{(i)}), i=1,... ,p-1 \\&lt;br /&gt;
\mid  N_\varepsilon (x^{(i)}) \mid \ge MinPts, i=1,... ,p-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;MinPts&amp;lt;/math&amp;gt; задаётся пользователем и регулирует порог «шума». Согласно второму условию, у точек, находящихся внутри кластера, должно быть не менее &amp;lt;math&amp;gt;MinPts \   \varepsilon&amp;lt;/math&amp;gt; -соседей. Такие точки называются «ядрами». Остальные точки разделяются на граничные (имеющие менее &amp;lt;math&amp;gt;MinPts \   \varepsilon &amp;lt;/math&amp;gt; -cоседей, но достижимые из какого-либо «ядра») и шумовые. Две точки связны, если существует «ядро», из которого они обе достижимы.&lt;br /&gt;
При такой постановке задачи, под кластером понимается максимальное связное подмножество множества &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; . Точки, не попавшие в какой-либо кластер (не принадлежащие &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; -окрестности какого-либо «ядра»), относятся к классу «шум».&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром алгоритма является нахождение &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;-соседей каждого объекта входного множества &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt;. На эту часть алгоритма приходится основное время работы алгоритма, так как требуется найти всех соседей для каждого объекта заданного множества. Основные операции, которые применяются в вычислительном ядре  алгоритма: нахождение расстояние между объектами и сравнение расстояния с порогом для определения того, являются ли данные объекты &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;-соседями.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма == &lt;br /&gt;
Алгоритм DBSCAN использует пространственную структуру данных для определения соседних объектов. Такие структуры данных позволяют найти все объекты в пределах определенного расстояния от текущего объекта. Сложность построения таких структур &amp;lt;math&amp;gt;O(n \log n)&amp;lt;/math&amp;gt;, и использование такой структуры не увеличит сложность всего алгоритма (если сложность самого алгоритма &amp;lt;math&amp;gt;O(n \log n)&amp;lt;/math&amp;gt;). Также для построения таких деревьев нужно уметь находить расстояния между объектами &amp;lt;math&amp;gt;\rho(u,v)&amp;lt;/math&amp;gt;, это расстояние можно вводить разными способами. Например, если &amp;lt;math&amp;gt;\rho(u,v)&amp;lt;/math&amp;gt; - метрика в евклидовом пространстве, &amp;lt;math&amp;gt;u=(u_1,...,u_n)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;(v_1,...,v_n)&amp;lt;/math&amp;gt;, то расстояние вычисляется следующим образом: &amp;lt;math&amp;gt;\rho(u,v)=\sqrt{(u_1-v_1)^2+(u_2-v_2)^2+...+(u_n-v_n)^2} = \sqrt{\sum_{k=1}^n(u_k-v_k)^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Последовательная реализация алгоритма может быть представлена следующим псевдокодом:&lt;br /&gt;
&lt;br /&gt;
 // Основная функция, которая реализует алгоритм кластеризации&lt;br /&gt;
 &amp;lt;math&amp;gt;DBSCAN(X, \varepsilon, MinPts)&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;FORALL&amp;lt;/math&amp;gt;  objects  &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; in &amp;lt;math&amp;gt;X\  DO&amp;lt;/math&amp;gt;&lt;br /&gt;
       &amp;lt;math&amp;gt;IF\  x&amp;lt;/math&amp;gt; is unclassified&lt;br /&gt;
         call function &amp;lt;math&amp;gt;expand\_cluster&amp;lt;/math&amp;gt; to construct a cluster wrt. &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; and &amp;lt;math&amp;gt;MinPts&amp;lt;/math&amp;gt; containing &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 // Функция, которая строит кластер на основе одной точки&lt;br /&gt;
 &amp;lt;math&amp;gt;FUNCTION\ expand\_cluster(x,X,\varepsilon, MinPts):&amp;lt;/math&amp;gt;&lt;br /&gt;
    &amp;lt;math&amp;gt;retrive\_\varepsilon neighborhood(x, \varepsilon)&amp;lt;/math&amp;gt;;&lt;br /&gt;
    &amp;lt;math&amp;gt;IF \mid N_{\varepsilon}(x) \mid &amp;lt; MinPts&amp;lt;/math&amp;gt; //т.е. &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; - объект, не являющийся ядром&lt;br /&gt;
       mark &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; as &amp;lt;math&amp;gt;noise&amp;lt;/math&amp;gt;  and &amp;lt;math&amp;gt;RETURN&amp;lt;/math&amp;gt;;&lt;br /&gt;
    &amp;lt;math&amp;gt;ELSE&amp;lt;/math&amp;gt;//т.е. &amp;lt;math&amp;gt;x&amp;lt;/math&amp;gt; - объект, являющийся ядром&lt;br /&gt;
       select a new cluster-id and mark all objects in &amp;lt;math&amp;gt;N_{\varepsilon}(x)&amp;lt;/math&amp;gt; with this current &amp;lt;math&amp;gt;cluster-id&amp;lt;/math&amp;gt;; &lt;br /&gt;
       push all objects from &amp;lt;math&amp;gt;N_{\varepsilon}(x)&amp;lt;/math&amp;gt;\&amp;lt;math&amp;gt;(x)&amp;lt;/math&amp;gt; onto the stack seeds;&lt;br /&gt;
       &amp;lt;math&amp;gt;WHILE\ NOT&amp;lt;/math&amp;gt; seeds.empty() &amp;lt;math&amp;gt;DO&amp;lt;/math&amp;gt; &lt;br /&gt;
         &amp;lt;math&amp;gt;currentObject&amp;lt;/math&amp;gt; := seeds.top();&lt;br /&gt;
         seeds.pop();&lt;br /&gt;
         &amp;lt;math&amp;gt;retrive\_\varepsilon neighborhood(currentObject, \varepsilon)&amp;lt;/math&amp;gt;;&lt;br /&gt;
         &amp;lt;math&amp;gt;IF \mid N_{\varepsilon}(currentObjects) \mid \ge MinPts&amp;lt;/math&amp;gt;&lt;br /&gt;
           select all objects in &amp;lt;math&amp;gt;N_{\varepsilon}(currentObject)&amp;lt;/math&amp;gt; not yet classified or marked as &amp;lt;math&amp;gt;noise&amp;lt;/math&amp;gt;,&lt;br /&gt;
           push the unclassified objects onto seeds and mark all of these objects with current &amp;lt;math&amp;gt;cluster-id&amp;lt;/math&amp;gt;;&lt;br /&gt;
     &amp;lt;math&amp;gt;RETURN&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 // Функция, для определения &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;-соседей для объекта&lt;br /&gt;
 &amp;lt;math&amp;gt;FUNCTION\ retrive\_\varepsilon neighborhood(x, \varepsilon)&amp;lt;/math&amp;gt; //функция возвращает соседей на основе пространственной структуры данных&lt;br /&gt;
   return &amp;lt;math&amp;gt;\{ x&#039; \ | \ \forall x&#039; \in X: \rho(x, x&#039;) &amp;lt; \varepsilon \}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
Для того, чтобы алгоритм мог кластеризовать все объекты, необходимо пройти по каждому из них хотя бы один раз. Если использовать R*-дерево или kd-дерево для определения соседних объектов со сложностью &amp;lt;math&amp;gt;O(\log n)&amp;lt;/math&amp;gt;, то сложность алгоритма &amp;lt;math&amp;gt;O(n \log 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;
[[File:Dbscan_schema.jpg|1000px|thumb|center|Рис.1. Общая информационная структура алгоритма]]&lt;br /&gt;
Разбиение данных происходит с помощью пространственной структуры данных (R*-дерево, kd-дерево), которая разбивает все множество объектов &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; на &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; частей: &amp;lt;math&amp;gt;X_1,X_2,...,X_m&amp;lt;/math&amp;gt;.&lt;br /&gt;
На каждой части объектов применяется алгоритм PDBSCAN. PDBSCAN - это последовательный алгоритм DBSCAN, применяемый только к одной части объектов, и для каждой из этих частей он определяет кандидатов на слияние. PDBSCAN использует пространственную структуру, которая распределяется вместе с данными.&lt;br /&gt;
Если для ядрового объекта части &amp;lt;math&amp;gt;X_i&amp;lt;/math&amp;gt; в &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;-окрестности находится объект из другой части &amp;lt;math&amp;gt;X_j&amp;lt;/math&amp;gt;, то такие объекты становятся кандидатами на слияние. &lt;br /&gt;
&lt;br /&gt;
Само слияние осуществляется следующим образом: для каждой пары кандидатов на слияние, объединяем кластеры, соответствующие этим кандидатам в один общий кластер.&lt;br /&gt;
&lt;br /&gt;
[[File:dbscan_clusters_partitions.png|500px|thumb|center|Рис.2. Пример разбиения объектов на части на основе пространственной структуры. Каждый прямоугольник соответствует части данных, каждая из которых подается на вход алгоритму PDBSCAN &amp;lt;ref&amp;gt;https://github.com/bwoneill/pypardis/blob/master/plots/median_search_split/clusters_partitions.png&amp;lt;/ref&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Как видно из общей структуры графа алгоритма, ширина ярусно-параллельной формы алгоритма &amp;lt;math&amp;gt;O(m)&amp;lt;/math&amp;gt;, где m - количество частей, на которые разбиваются все входное множество объектов &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt;. Высотой ярусно-параллельной формы алгоритма является &amp;lt;math&amp;gt;O(|X| \log |X|)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\mid X \mid&amp;lt;/math&amp;gt; - максимальное количество среди числа объектов в каждой части разбиения. Именно такую сложность имеет алгоритм PDBSCAN, применяемый к каждой отдельной части разбиения.&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные&#039;&#039;&#039;: множество точек X из n-мерного пространства, на котором определена функция расстояния D. В наиболее распространенном случае пространственной кластеризации используется Евлидова метрика между векторами из &amp;lt;math&amp;gt;{R}^n&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём входных данных&#039;&#039;&#039;: n (размерность входящего множества)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные&#039;&#039;&#039;: размеченное множество точек X, в котором каждой точке соответствует номер ее кластера. Обычно каждой точке из X сопоставляется ее номер, а на выходе алгоритм дает отображение номеров точек в номера соответствующих им кластеров, например в виде вектора размера |X|&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Объём выходных данных&#039;&#039;&#039;: n (размерность выходящего множества)&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;
* параллельная реализация сбалансирована по количеству и виду производимых операций (вычисление расстояния, сравнение с &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;);&lt;br /&gt;
* не требуется задание числа кластеров;&lt;br /&gt;
* может выделять кластеры в присутствии «шума»и выбросов &amp;lt;ref&amp;gt;АЛГОРИТМЫ КЛАСТЕРИЗАЦИИ В ЗАДАЧАХ СЕГМЕНТАЦИИ&lt;br /&gt;
СПУТНИКОВЫХ ИЗОБРАЖЕНИЙ/ И. А. Пестунов, Ю. Н. Синявский// Вестник Кемеровского государственного университета. – 2012. – P. 263–&lt;br /&gt;
299.&amp;lt;/ref&amp;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;
* не детерминирован, так как граничные точки, достижимые из более, чем одного кластера, могут быть частью любого из них в зависимости от порядка обрабатываемых данных. Однако такая ситуация возникает редко, а относительно ядровых точек и шума DBSCAN детерминирован.&lt;br /&gt;
* плохо работает на кластерах, которые имеют небольшое пересечение между собой.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
Было проведено исследование масштабируемости параллельной реализации алгоритма DBSCAN . Исследование проводилось на суперкомпьютере &amp;quot;Ломоносов&amp;quot; [http://parallel.ru/cluster Суперкомпьютерного комплекса Московского университета]. Исследовалась параллельная реализация алгоритма, написанная с использованием стандарта MPI. Распараллеливание проводилось по числу входных объектов, поэтому исследование масштабируемости проводилось для числа входных объектов.  Алгоритм тестировался на известном датасете для кластеризации: [https://archive.ics.uci.edu/ml/datasets/Individual+household+electric+power+consumption Machine Learning Repository]&lt;br /&gt;
&lt;br /&gt;
Набор и границы значений изменяемых [[Глоссарий#Параметры запуска|параметров запуска]] реализации алгоритма: &lt;br /&gt;
&lt;br /&gt;
*	число процессоров [1 : 128] с шагом по степеням двойки;&lt;br /&gt;
*	число входных объектов [1000 : 40000].&lt;br /&gt;
&lt;br /&gt;
На следующих рисунках приведены графики производительности и эффективности распараллеливания алгоритма DBSCAN в зависимости от изменяемых параметров запуска.&lt;br /&gt;
[[File:Dbscan_perfomance.png|800px|thumb|center|Рис.1. Изменение производительности в зависимости от числа процессов и числа входных данных]]&lt;br /&gt;
[[File:Dbscan_efficiency.png|800px|thumb|center|Рис.2. Изменение эффективности распараллеливания в зависимости от числа процессов и числа входных данных]]&lt;br /&gt;
&lt;br /&gt;
Построим оценки масштабируемости протестированной параллельной реализации алгоритма DBSCAN: &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;По числу процессов&#039;&#039;&#039; - при увеличении числа процессов наблюдается уменьшение эффективности на всей области рассматриваемых значений параметров. При этом с ростом числа процессов снижение эффективности замедляется. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;По размеру задачи&#039;&#039;&#039; - При увеличении размерности системы при фиксированном количестве процессов на области изменений значений параметров наблюдается увеличение эффективности. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;При одновременном увеличении количества процессов и размерности системы&#039;&#039;&#039; наблюдается уменьшение эффективности. При этом скорость убывания эффективности крайне низкая.&lt;br /&gt;
&lt;br /&gt;
[https://github.com/elena777mc/dbscan/tree/master Исследованная параллельная реализация на языке C++]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* [http://scikit-learn.org/stable/modules/generated/sklearn.cluster.DBSCAN.html Scikit learn (Python, последовательная реализация)]&lt;br /&gt;
* [http://cucis.ece.northwestern.edu/projects/Clustering/download_code_dbscan.html Northwestern University (C++, параллельная реализация kd-tree)]&lt;br /&gt;
* [https://github.com/ContinuumIO/parallel_dbscan github/ContinuumIO (Python, параллельная реализация)]&lt;br /&gt;
* [https://github.com/propanoid/DBSCAN github/propanoid (C++, последовательная реализация VP tree)]&lt;br /&gt;
* [https://github.com/dparks1134/DBSCAN github/dparks1134 (С++, последовательная реализация)]&lt;br /&gt;
* [https://github.com/ahbarnett/validspike/tree/master/contrib/dbscan_patwary Disjoint-Set Data Structure based Parallel DBSCAN (C++ параллельная реализация kd-tree)]&lt;br /&gt;
* [https://github.com/bwoneill/pypardis github/bwoneill (Spark/Python параллельная реализация kd-tree)]&lt;br /&gt;
* [https://github.com/alitouka/spark_dbscan github/alitouka (Spark/Scala параллельная реализация)]&lt;br /&gt;
* [https://github.com/mhahsler/dbscan CRAN (R, последовательная реализация)]&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&amp;lt;references \&amp;gt;&lt;br /&gt;
&amp;lt;references \&amp;gt;[https://pdfs.semanticscholar.org/a3f8/a3948e5999def4a0819d0dbaef2ae05e1599.pdf (A Fast Parallel Clustering Algorithm for Large Spatial Databases, JOCHEN JAGER, HANS-PETER KRIEGEL)]&lt;br /&gt;
&amp;lt;references \&amp;gt;[http://cyberleninka.ru/article/n/algoritmy-klasterizatsii-v-zadachah-segmentatsii-sputnikovyh-izobrazheniy (АЛГОРИТМЫ КЛАСТЕРИЗАЦИИ В ЗАДАЧАХ СЕГМЕНТАЦИИ СПУТНИКОВЫХ ИЗОБРАЖЕНИЙ, Пестунов Игорь Алексеевич, Синявский Юрий Николаевич)]&lt;br /&gt;
&lt;br /&gt;
[[en:Cholesky decomposition]]&lt;br /&gt;
&lt;br /&gt;
[[Категория:Законченные статьи]]&lt;/div&gt;</summary>
		<author><name>Dexter</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:Dadrik/%D0%9F%D0%BB%D0%BE%D1%82%D0%BD%D0%BE%D1%81%D1%82%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&amp;diff=19365</id>
		<title>Участник:Dadrik/Плотностный алгоритм кластеризации</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:Dadrik/%D0%9F%D0%BB%D0%BE%D1%82%D0%BD%D0%BE%D1%81%D1%82%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&amp;diff=19365"/>
		<updated>2016-11-28T14:57:30Z</updated>

		<summary type="html">&lt;p&gt;Dexter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Преподаватель 1|Dexter}}&lt;br /&gt;
{{Assignment|Sleo}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Плотностный алгоритм кластеризации DBSCAN&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(n \log 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;
Авторы описания: [[Участник:Dadrik | Вашуров И.М.]], [[Участник:ramon93i7 | Шемякин Р.О.]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Задача кластеризации - это задача разбиения заданной входной выборки объектов на непересекающиеся подмножества, называемые кластерами, так, чтобы каждый кластер состоял из схожих объектов, а объекты разных кластеров существенно отличались.&lt;br /&gt;
&lt;br /&gt;
Алгоритм DBSCAN (Density-based spatial clustering of applications with noise)&amp;lt;ref&amp;gt;Ester, Martin, et al. &amp;quot;A density-based algorithm for discovering clusters in large spatial databases with noise.&amp;quot; Kdd. Vol. 96. No. 34. 1996.&amp;lt;/ref&amp;gt; был предложен Мартином Эстер, Гансом-Питером Кригель и коллегами в 1996 году как решение задачи кластеризации с кластерами произвольной формы. DBSCAN является непараметрическим плотностным алгоритмом кластеризации: для заданного набора точек в некотором пространстве, алгоритм группирует те точки, которые расположены достаточно близко друг к другу (точки с большим количеством соседей), и помечает как выбросы те, что располагаются далеко от ближайших соседей.&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;X&amp;lt;/math&amp;gt; из &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;-мерного пространства, на котором определена функция расстояния &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Выход алгоритма: размеченное множество точек &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt;, в котором каждой точке соответствует номер ее кластера.&lt;br /&gt;
&lt;br /&gt;
Параметры алгоритма: &lt;br /&gt;
* &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt; - максимальное расстояние между соседями;&lt;br /&gt;
* &amp;lt;math&amp;gt;MinPts&amp;lt;/math&amp;gt; - минимальное количество соседей для создания области связности.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Определения ===&lt;br /&gt;
&lt;br /&gt;
[[File:Cluster_scheme.png|thumb|right|400px| Рис. 1. [https://upload.wikimedia.org/wikipedia/commons/a/af/DBSCAN-Illustration.svg] Здесь &#039;&#039;MinPts&#039;&#039; = 4. Точка &#039;&#039;A&#039;&#039; и другие красные точки - ядровые и образуют единый кластер, так как достижимы друг из друга. Точки &#039;&#039;B&#039;&#039; и &#039;&#039;C&#039;&#039; не являются ядровыми, но достижимы из &#039;&#039;A&#039;&#039;, а значит также принадлежат кластеру. Точка &#039;&#039;N&#039;&#039; - не достижима из других точек и является шумом.]]&lt;br /&gt;
&lt;br /&gt;
Все заданные точки классифицируются на три группы:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;ядровые точки&#039;&#039;: точка &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; является ядровой, если количество &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;-соседей, включая саму точку &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, не меньше &amp;lt;math&amp;gt;MinPts&amp;lt;/math&amp;gt;. Под &#039;&#039;&amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;-соседями&#039;&#039; точки &amp;lt;math&amp;gt;p \in X&amp;lt;/math&amp;gt; понимается множество точек, расстояние до которых не превышает &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;, т.е. &amp;lt;math&amp;gt;N_\varepsilon(p) = \{ x \in X | D(p, x) \le \varepsilon \}&amp;lt;/math&amp;gt;. Эти точки являются напрямую достижимыми из &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;достижимые точки&#039;&#039;: точка &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; достижима из &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, если  существует путь &amp;lt;math&amp;gt;p_1, \dots, p_n&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;p_1 = p&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;p_n = q&amp;lt;/math&amp;gt;, для которого выполнено: &lt;br /&gt;
:&amp;lt;math&amp;gt;\begin{align}&lt;br /&gt;
p_{i + 1} \in N_\varepsilon(p_i),  i = 1, \dots, n-1 \\&lt;br /&gt;
| N_\varepsilon(p_{i}) | \ge MinPts, i = 1, \dots, n-1 \\&lt;br /&gt;
\end{align}&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;p&amp;lt;/math&amp;gt; - ядровая точка, то она образует кластер вместе со всеми точками, достижимыми из неё. Каждый кластер содержит по крайней мере одну ядровую точку; неядровые точки могут быть частью кластера, образуя при этом его &amp;quot;границу&amp;quot;, так как они не могут быть использованы для достижения других точек.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Достижимость не является симметричным отношением, так как по определению никакая точка не может быть достижима из неядровой точки, независимо от расстояния. Поэтому в DBSCAN применяется следующий термин &#039;&#039;связности&#039;&#039;: две точки &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; связанны, если существует такая точка &amp;lt;math&amp;gt;o&amp;lt;/math&amp;gt;, что &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;q&amp;lt;/math&amp;gt; достижимы из &amp;lt;math&amp;gt;o&amp;lt;/math&amp;gt;. Такое отношение связности симметрично.&lt;br /&gt;
&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;
#Выбирается произвольная непосещенная точка &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;.&lt;br /&gt;
#Точка &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; помечается как посещенная. &lt;br /&gt;
#У точки &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; определяется множество её &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;-соседей - &amp;lt;math&amp;gt;N_\varepsilon(p)&amp;lt;/math&amp;gt;.&lt;br /&gt;
#*Если точка &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; оказалась ядровой - &amp;lt;math&amp;gt;| N_\varepsilon(p) | \ \ge MinPts&amp;lt;/math&amp;gt;, то: &lt;br /&gt;
#**она становится началом нового кластера или сохраняет номер кластера, который был ей присвоен ранее; &lt;br /&gt;
#**все точки из &amp;lt;math&amp;gt;N_\varepsilon(p)&amp;lt;/math&amp;gt; добавляются в её кластер;&lt;br /&gt;
#**процесс продолжается рекурсивно для каждой новой добавленной непосещенной точки &amp;lt;math&amp;gt;p&#039; \in N_\varepsilon(p)&amp;lt;/math&amp;gt; c шага 2 (в качестве новой &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;).&lt;br /&gt;
#*Если точка &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; оказалась не ядровой, то &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; объявляется шумом. Алгоритм продолжается с шага 4.&lt;br /&gt;
#Если остались непосещенные точки, то алгоритм продолжается с шага 1.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительным ядром алгоритма является нахождение &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;-соседей каждой точки входного множества &amp;lt;math&amp;gt;X&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;k&amp;lt;/math&amp;gt;, то расстояние между точками &amp;lt;math&amp;gt;p=(p_1,...,p_n) \in X&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;q=(q_1,...,q_n) \in X&amp;lt;/math&amp;gt; вычисляется как &amp;lt;math&amp;gt;D(p, q) = (\sum_{i = 1}^{n}|p_i - q_i|^k)^{1 / k}&amp;lt;/math&amp;gt;, частным случаем которой при &amp;lt;math&amp;gt;k = 2&amp;lt;/math&amp;gt; является широко распространённая евклидова метрика &amp;lt;math&amp;gt;D(p, q) = \sqrt{\sum_{i = 1}^{n} (p_i - q_i)^2}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Как записано и в [[#Вычислительное ядро алгоритма|описании ядра алгоритма]], основную часть метода составляют вызовы функции &amp;lt;math&amp;gt;request\_neighbours&amp;lt;/math&amp;gt; получения &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;-соседей и нахождение расстояний между точками множества &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;DBSCAN&amp;lt;/math&amp;gt; проходит через все точки множества &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и определяет, являются ли они шумом или началом нового кластера. &lt;br /&gt;
В последнем случае новому кластеру присваивается уникальный номер и вызывается функция расширения кластера.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;math&amp;gt;DBSCAN(\varepsilon, MinPts)&amp;lt;/math&amp;gt;&lt;br /&gt;
   &amp;lt;math&amp;gt;C = 0&amp;lt;/math&amp;gt;&lt;br /&gt;
   for &amp;lt;math&amp;gt;\forall p \in X&amp;lt;/math&amp;gt;&lt;br /&gt;
      if &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; is visited then&lt;br /&gt;
         continue&lt;br /&gt;
      mark &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; as visited&lt;br /&gt;
      &amp;lt;math&amp;gt;neighbours&amp;lt;/math&amp;gt; = &amp;lt;math&amp;gt;request\_neighbours(p, \varepsilon)&amp;lt;/math&amp;gt;&lt;br /&gt;
      if &amp;lt;math&amp;gt;| neighbours | &amp;lt; MinPts&amp;lt;/math&amp;gt; then&lt;br /&gt;
         mark &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; as &amp;lt;math&amp;gt;NOISE&amp;lt;/math&amp;gt;&lt;br /&gt;
      else&lt;br /&gt;
         &amp;lt;math&amp;gt;C = next\_cluster&amp;lt;/math&amp;gt;&lt;br /&gt;
         &amp;lt;math&amp;gt;expand\_cluster(p, neighbours, C, \varepsilon, MinPts)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;expand\_cluster&amp;lt;/math&amp;gt; рекурсивно проходит через все точки множества &amp;lt;math&amp;gt;neighbours&amp;lt;/math&amp;gt; - соседей точки &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt;, &lt;br /&gt;
и определяет, принадлежат ли эти точки тому же кластеру &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;, тем самым расширяя этот кластер.&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;math&amp;gt;expand\_cluster(p, neighbours, C, \varepsilon, MinPts)&amp;lt;/math&amp;gt;&lt;br /&gt;
   add &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; to cluster &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&lt;br /&gt;
   for &amp;lt;math&amp;gt;\forall p&#039; \in neighbours&amp;lt;/math&amp;gt;&lt;br /&gt;
      if &amp;lt;math&amp;gt;p&#039;&amp;lt;/math&amp;gt; is not visited &lt;br /&gt;
         mark &amp;lt;math&amp;gt;p&#039;&amp;lt;/math&amp;gt; as visited&lt;br /&gt;
         &amp;lt;math&amp;gt;neighbours&#039;&amp;lt;/math&amp;gt; = &amp;lt;math&amp;gt;request\_neighbours(p, \varepsilon)&amp;lt;/math&amp;gt;&lt;br /&gt;
         if &amp;lt;math&amp;gt;| neighbours&#039; | \ \ge MinPts&amp;lt;/math&amp;gt;&lt;br /&gt;
            &amp;lt;math&amp;gt;neighbours&amp;lt;/math&amp;gt; = &amp;lt;math&amp;gt;neighbours \cup neighbours&#039;&amp;lt;/math&amp;gt;  &lt;br /&gt;
      if &amp;lt;math&amp;gt;p&#039;&amp;lt;/math&amp;gt; is not yet member of any cluster&lt;br /&gt;
         add &amp;lt;math&amp;gt;p&#039;&amp;lt;/math&amp;gt; to cluster &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;request\_neighbours&amp;lt;/math&amp;gt; возвращает для точки &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; множество всех её &amp;lt;math&amp;gt;\varepsilon&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;request\_neighbours(p, \varepsilon)&amp;lt;/math&amp;gt;&lt;br /&gt;
    return &amp;lt;math&amp;gt;\{ p&#039; \ | \ \forall p&#039; \in X: D(p, p&#039;) &amp;lt; \varepsilon \}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
DBSCAN проходит через каждую точку входного множества, возможно, по несколько раз. Временная сложность зависит в большей степени от вызова функции &amp;lt;math&amp;gt;request\_neighbours&amp;lt;/math&amp;gt; (нахождение &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;-соседей для заданной точки). Эта функция вызывается ровно один раз для каждой точки множества &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Если использовать индексированную структуру данных (например, R-деревья), выполняющую операцию &amp;lt;math&amp;gt;request\_neighbours&amp;lt;/math&amp;gt; за &amp;lt;math&amp;gt;O(\log n)&amp;lt;/math&amp;gt;, то суммарная сложность алгоритма в среднем составит &amp;lt;math&amp;gt;O(n \log n)&amp;lt;/math&amp;gt;, с учётом хорошо подобранного параметра &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;, такого что в среднем &amp;lt;math&amp;gt;request\_neighbours&amp;lt;/math&amp;gt; возвращает &amp;lt;math&amp;gt;O(\log n)&amp;lt;/math&amp;gt; точек. Без использования ускоряющих структур или на вырожденных данных (таких, что все точки находятся на расстоянии меньшем, чем &amp;lt;math&amp;gt;\varepsilon&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;
Расстояния между точками можно вычислить заранее за &amp;lt;math&amp;gt;O(\frac {n(n - 1)}{2})&amp;lt;/math&amp;gt;, например в виде матрицы расстояний, но это потребует &amp;lt;math&amp;gt;O(n^2)&amp;lt;/math&amp;gt; памяти. Иначе, расстояния будут вычисляться при каждом запуске функции &amp;lt;math&amp;gt;request\_neighbours&amp;lt;/math&amp;gt; за &amp;lt;math&amp;gt;O(n)&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;. Сложность рассчета расстояний зависит от природы объектов из &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и заданной метрики &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;. Например, если &amp;lt;math&amp;gt;X\subset\mathbb{R}^m&amp;lt;/math&amp;gt;, то сложность равна &amp;lt;math&amp;gt;O(m)&amp;lt;/math&amp;gt;, но оценка может быть улучшена при использовании векторных операций.&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&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;
&lt;br /&gt;
[[File:Dbscan abstract.png |thumb|right|320px| Рис. 2. Внешний цикл алгоритма.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
На рис. 2 изображен информационный граф внешнего цикла алгоритма, который соответствует коду основной функции &amp;lt;math&amp;gt;DBSCAN&amp;lt;/math&amp;gt;:&lt;br /&gt;
*Макрооперация &#039;&#039;Init&#039;&#039; заключается в получении множества &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; и инициирования вспомогательных структур. &lt;br /&gt;
*Макрооперация &#039;&#039;Choose&#039;&#039; производит выбор непосещенной точки из &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt;.&lt;br /&gt;
*Макрооперация &#039;&#039;Build cluster&#039;&#039; строит кластер, если точка ядровая, или объявляет ее шумом.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Переход от &#039;&#039;Build cluster&#039;&#039; к &#039;&#039;Choose&#039;&#039; заключает в себе зависимость данных о принадлежности некоторых точек к текущему кластеру или шуму и об их посещенности.&lt;br /&gt;
&lt;br /&gt;
[[File:Expand cluster 2.png |thumb|right|600px| Рис. 3. Расширение кластера.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
На рис. 3 изображен информационный граф алгоритма расширения кластера из начальной точки кластера:&lt;br /&gt;
*Макрооперация &#039;&#039;Init&#039;&#039; заключается в создании кластера из его начальной вершины.&lt;br /&gt;
*Макрооперация &#039;&#039;Nε&#039;&#039; вычисляет множество &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;-соседей.&lt;br /&gt;
*Желтым цветом обозначены узлы, в которых точки из &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;-соседей классифицируются на ядровые, граничные точки и шум. В рамках операции для конкретного соседа вычисляется множество его &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;-соседей.&lt;br /&gt;
*Макрооперации &#039;&#039;Ñε&#039;&#039;, &#039;&#039;Ňε&#039;&#039;, ... производят объединение входных множеств.&lt;br /&gt;
*Макрооперация &#039;&#039;Ø&#039;&#039; выполняется тогда, когда объединение входных множеств является пустым.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:N eps 3.png         |thumb|right|320px| Рис. 4. Подсчет &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;-соседей.]]&lt;br /&gt;
&lt;br /&gt;
На рис. 4 изображен информационный граф алгоритма вычисления множества &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;-соседей:&lt;br /&gt;
*Операция &#039;&#039;D&#039;&#039; - вычисление расстояния между точками.&lt;br /&gt;
*Операция &#039;&#039;ε&#039;&#039; - сравнение расстояния с ε.&lt;br /&gt;
*Операция &#039;&#039;U&#039;&#039; - объединение результатов.&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Поиск &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;-соседей требует вычисления &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; расстояний (функция &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;) и выполнения &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; сравнений с &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;. Эти операции для каждой пары точек независимы и могут быть выполнены параллельно. Таким образом, при наличии неограниченного числа процессоров сложность поиска составит &amp;lt;math&amp;gt;O(1)&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;
&lt;br /&gt;
Вход алгоритма: множество точек X из n-мерного пространства, на котором определена функция расстояния D. В наиболее распространенном случае пространственной кластеризации используется Евлидово расстояние между векторами из &amp;lt;math&amp;gt;\mathbb{R}^n&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;X&amp;lt;/math&amp;gt; сопоставляется ее номер, а на выходе алгоритм дает отображение номеров точек в номера соответствующих им кластеров, например в виде вектора размера &amp;lt;math&amp;gt;|X|&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;
# параллельная реализация сбалансирована по количеству и виду производимых операций (вычисление расстояния, сравнение с &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
=== Недостатки алгоритма ===&lt;br /&gt;
&lt;br /&gt;
# не детерминирован: граничные точки, достижимые из более, чем одного кластера, могут быть частью любого из них в зависимости от порядка обрабатываемых данных. Однако такая ситуация возникает редко, а относительно ядровых точек и шума DBSCAN детерминирован. Впрочем, от недетерминизма можно избавиться, если считать все граничные точки шумом (алгоритм DBSCAN*);&lt;br /&gt;
# качество алгоритма зависит от используемой функции расстояния &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;. Наиболее часто используемое Евклидово расстояние в многомерных множествах может оказаться практически бесполезным из-за так называемого &amp;quot;проклятия размерности&amp;quot;, значительно затрудняя нахождение подходящего значения &amp;lt;math&amp;gt;\varepsilon&amp;lt;/math&amp;gt;;&lt;br /&gt;
# не может выделять кластеры, имеющие разную плотность, так как параметры алгоритма не могут быть выбранны отдельно для каждого кластера.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
!!! ЭКСПЕРИМЕНТЫ ДО 15 НОЯБРЯ !!!&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* [http://scikit-learn.org/stable/modules/generated/sklearn.cluster.DBSCAN.html Scikit learn (Python)]&lt;br /&gt;
* [https://cran.r-project.org/web/packages/dbscan/dbscan.pdf R-project] ([https://github.com/mhahsler/dbscan github])&lt;br /&gt;
* [https://www.mathworks.com/matlabcentral/fileexchange/52905-dbscan-clustering-algorithm Matlab]&lt;br /&gt;
* P-DBSCAN (Parallel DBSCAN)&amp;lt;ref&amp;gt;Chen, Min, Xuedong Gao, and HuiFei Li. &amp;quot;Parallel DBSCAN with priority r-tree.&amp;quot; Information Management and Engineering (ICIME), 2010 The 2nd IEEE International Conference on. IEEE, 2010.&amp;lt;/ref&amp;gt;&lt;br /&gt;
* Parallel DBSCAN with MPI&amp;lt;ref&amp;gt;Savvas, Ilias K., and Dimitrios Tselios. &amp;quot;Parallelizing DBSCaN Algorithm Using MPI.&amp;quot; Enabling Technologies: Infrastructure for Collaborative Enterprises (WETICE), 2016 IEEE 25th International Conference on. IEEE, 2016.&amp;lt;/ref&amp;gt;&lt;br /&gt;
* PDSDBSCAN (Parallel Disjoint-Set DBSCAN)&amp;lt;ref&amp;gt;Patwary, Md Mostofa Ali, et al. &amp;quot;A new scalable parallel DBSCAN algorithm using the disjoint-set data structure.&amp;quot; High Performance Computing, Networking, Storage and Analysis (SC), 2012 International Conference for. IEEE, 2012.&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>Dexter</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:Maria_Zaitseva&amp;diff=19295</id>
		<title>Обсуждение участника:Maria Zaitseva</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:Maria_Zaitseva&amp;diff=19295"/>
		<updated>2016-11-27T19:35:57Z</updated>

		<summary type="html">&lt;p&gt;Dexter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Новые замечания&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
1) В верхней врезке нет свойств параллельной версии алгоритма (см страницу-образец)&lt;br /&gt;
&lt;br /&gt;
2) Называть множества маленькими буквами - плохая идея&lt;br /&gt;
&lt;br /&gt;
3) На рис.2 показана ситуация для шага t, но буква t не участвует в подписях на рисунке&lt;br /&gt;
&lt;br /&gt;
== Статья [[Участник:Maria Zaitseva/PAM (Partitioning Around Medoids)]] ==&lt;br /&gt;
&lt;br /&gt;
=== Замечания по тексту ===&lt;br /&gt;
* Название статьи лучше дать в развёрнутом виде. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 16:53, 27 октября 2016 (MSK)&lt;br /&gt;
* В разделе 1.4 нужно не дублировать информацию из раздела 1.3, а описать алгоритм на верхнем уровне. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 16:53, 27 октября 2016 (MSK)&lt;br /&gt;
* В разделе 1.5 кроме псевдокода требуются текстовые пояснения. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 16:53, 27 октября 2016 (MSK)&lt;br /&gt;
* В разделе 1.5 требуются указать объёмы входных и выходных данных. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 16:53, 27 октября 2016 (MSK)&lt;br /&gt;
** Имелся в виду раздел 1.9, конечно же. &lt;br /&gt;
* В разделе 2.4 не приведены все параметры запуска теста - какой компилятор, с какими опциями использовался, какая версия MPI, на каких узлах проводился запуск и т.д. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 15:16, 16 ноября 2016 (MSK) &lt;br /&gt;
&lt;br /&gt;
=== Отсутствующие части ===&lt;br /&gt;
* Не указан вклад каждого из авторов статьи. [[Участник:ASA|Александр Сергеевич Антонов]] ([[Обсуждение участника:ASA|обсуждение]]) 16:53, 27 октября 2016 (MSK)&lt;/div&gt;</summary>
		<author><name>Dexter</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:Denemmy/Partitioning_Around_Medoids_(%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC)&amp;diff=19294</id>
		<title>Участник:Denemmy/Partitioning Around Medoids (Алгоритм)</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:Denemmy/Partitioning_Around_Medoids_(%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC)&amp;diff=19294"/>
		<updated>2016-11-27T19:28:51Z</updated>

		<summary type="html">&lt;p&gt;Dexter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Преподаватель 1|Dexter}}&lt;br /&gt;
{{Assignment|Zhum}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Partitioning Around Medoids&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(T*K*N^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt; N*(N-1)/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;
Авторы: [[Участник:Denemmy|Галеев Д.Ф]], [[Участник:zaputlyaev|Запутляев И.]]&lt;br /&gt;
&lt;br /&gt;
Оба автора в равной мере участвовали в написании, обсуждении и оформлении содержимого статьи.&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Кластеризация&#039;&#039;&#039; - это задача из области машинного обучения, которая заключается в том, что нужно выделить некоторое число групп в исходном множестве, в каждой из которых содержатся схожие по некоторой метрике элементы.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм &#039;&#039;&#039;Partitioning Around Medoids&#039;&#039;&#039; (&#039;&#039;&#039;PAM&#039;&#039;&#039;) был создан Леонардом Кауфманом (Leonard Kaufman) и Питером Руссивом (Peter J. Rousseeuw)&amp;lt;ref&amp;gt;Kaufman, L. and Rousseeuw, P.J., Clustering by means of Medoids. Statistical Data Analysis Based on the L1-Norm and Related Methods. Springer US; 1987, p. 405–416.&amp;lt;/ref&amp;gt;. и он очень похож на алгоритм K-means, в основном потому, что оба являются алгоритмами кластеризации, другими словами, оба разделяют множество объектов на группы (кластеры) и работа обоих основана на попытках минимизировать ошибку, но PAM работает с медоидами - объектами, являющимися частью исходного множества и представляющими группу, в которую они включены, а K-means работает с центроидами - искусственно созданными объектами, представляющими кластер.&lt;br /&gt;
&lt;br /&gt;
Алгоритм PAM разделяет множество из N объектов на K кластеров, где и множество объектов, и число K являются входными данными алгоритма. Алгоритм работает с матрицей расстояний, его цель - минимизировать расстояние между представителями каждого кластера и его членами. Алгоритм использует следующую модель для решения задачи:&amp;lt;ref&amp;gt;Fasulo D. An analysis of recent work on clustering algorithms. – Technical report, 1999. – №. 01-03. – С. 02.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;F(x)=minimize \sum_{i=1}^{N}\sum_{j=1}^{N} d(i,j)z_{ij}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом:&lt;br /&gt;
&lt;br /&gt;
1. &amp;lt;math&amp;gt; \sum_{i=1}^N {z_{ij} = 1} , j = 1,2,...,N&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
2. &amp;lt;math&amp;gt;z_{ij} \le y_i , i, j = 1,2,...,N&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
3. &amp;lt;math&amp;gt;\sum_{i=1}^N {y_i = K} , K - &amp;lt;/math&amp;gt; число кластеров;&lt;br /&gt;
&lt;br /&gt;
4. &amp;lt;math&amp;gt;y_i , z_{ij} \in \{ 0,1 \} , i, j = 1,2,...,N&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
где функция &amp;lt;math&amp;gt;F(x)&amp;lt;/math&amp;gt; - целевая минимизируемая функция, &amp;lt;math&amp;gt;d(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;z_{ij}&amp;lt;/math&amp;gt; - переменная, которая гарантирует, что расстояние только между объектами из одного кластера будет вычислено в целевой функции. Остальные выражения являются следующими ограничениями:&lt;br /&gt;
&lt;br /&gt;
1. Каждый объект принадлежит одному и только одному кластеру;&lt;br /&gt;
&lt;br /&gt;
2. Каждый объект относится к медоиде, представляющей его кластер;&lt;br /&gt;
&lt;br /&gt;
3. Есть в точности K кластеров;&lt;br /&gt;
&lt;br /&gt;
4. Решающая переменная принимает значения 0 или 1.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
PAM может работать с двумя типами входных данных:&lt;br /&gt;
&lt;br /&gt;
1. С матрицей объектов и значениями ее переменных;&lt;br /&gt;
&lt;br /&gt;
2. С матрицей расстояний.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Алгоритм имеет две фазы: &lt;br /&gt;
&lt;br /&gt;
Фаза &#039;&#039;&#039;Build&#039;&#039;&#039;:&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;
&lt;br /&gt;
Фаза &#039;&#039;&#039;Swap&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
4. Для каждого кластера найти объекты, снижающие среднее расстояние, и если такие объекты есть, выбрать те, которые снижают его сильней всего, в качестве медоид;&lt;br /&gt;
&lt;br /&gt;
5. Если хотя бы одна медоида поменялась, вернуться к шагу 3, иначе завершить алгоритм.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&#039;&#039;Обозначения&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
1. &amp;lt;math&amp;gt;M = \{ x_{m_1}, x_{m_2}, ... , x_{m_s} \} - &amp;lt;/math&amp;gt; множество медоид;&lt;br /&gt;
&lt;br /&gt;
2. &amp;lt;math&amp;gt;L = \{ x_{l_1}, x_{l_2}, ... , x_{m_t} \} - &amp;lt;/math&amp;gt; множество объектов &amp;lt;math&amp;gt;x_i&amp;lt;/math&amp;gt;, не являющихся медоидами;&lt;br /&gt;
&lt;br /&gt;
3. &amp;lt;math&amp;gt;F_{M,L} = \sum_{j = 1}^{N} \min_{ x_{m_q} \in M}  d(x_{m_q},x_{l_j}) - &amp;lt;/math&amp;gt; целевая функция.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Входные данные&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
1. Множество &amp;lt;math&amp;gt;X = \{ x_{1}, x_{2}, \dots, x_{N} \}&amp;lt;/math&amp;gt; объектов &amp;lt;math&amp;gt;x_i&amp;lt;/math&amp;gt;, каждый из который задается &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt; вещественными значениями;&lt;br /&gt;
&lt;br /&gt;
2. Симметрическая матрица &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, элементы &amp;lt;math&amp;gt;d_{ij} = d(x_i,x_j)&amp;lt;/math&amp;gt; которой являются расстояниями между объектами &amp;lt;math&amp;gt;x_i&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;x_j&amp;lt;/math&amp;gt;; &lt;br /&gt;
&lt;br /&gt;
3. Число кластеров &amp;lt;math&amp;gt;K \le N&amp;lt;/math&amp;gt;; &lt;br /&gt;
&lt;br /&gt;
4. Метрика &amp;lt;math&amp;gt;d_{ij} = d(x_i,x_j)&amp;lt;/math&amp;gt;, задающая расстояние между объектами &amp;lt;math&amp;gt;x_i&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;x_j&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Вычислительные формулы метода&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
Фаза &#039;&#039;&#039;Build&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
Представляет из себя выбор K медоид за K последовательных шагов:&lt;br /&gt;
&lt;br /&gt;
1. &amp;lt;math&amp;gt;M_0 = \varnothing, L_0 = X&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
2. &amp;lt;math&amp;gt;x_{m_i} = \arg \min_{x_{l_q} \in L_0} \sum_{j = 1}^N  d(x_{l_q},x_j), L_1 = L_0 \backslash \{x_{m_i}\}, M_1 = M_1 \cup \{x_{m_i}\}, i=1 \dots N &amp;lt;/math&amp;gt;; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Фаза &#039;&#039;&#039;Swap&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
Представляет из себя итерационный процесс.&lt;br /&gt;
&lt;br /&gt;
1. Начальное приближение: &amp;lt;math&amp;gt;M_0 = M_{BUILD}, L_0 = L_{BUILD}&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
2. Множественные вычисления значений целевой функции для различных вариантов замены текущей медоиды на новую:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;F = arg \min_{i \in M , j \in L} \sum_{y \in L \backslash \{j\}} {min (d(i,y),d(j,y))} &amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
3. Изменение множеств в соответствии с выбранной парой &amp;lt;math&amp;gt;(x_{m_t}, x_{l_q})&amp;lt;/math&amp;gt;: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;M_i = M_{i-1} \backslash \{x_{m_t}\} \cup \{x_{l_q}\} , L_i = L_{i-1} \cup \{x_{m_t}\} \backslash \{x_{l_q}\} &amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
4. Проверка критерия останова.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Выходные данные:&lt;br /&gt;
&lt;br /&gt;
1. &amp;lt;math&amp;gt;M = \{ x_{m_{1}}, x_{m_{2}}, ..., x_{m_{K}} \}&amp;lt;/math&amp;gt; - множество медоид;&lt;br /&gt;
&lt;br /&gt;
2. &amp;lt;math&amp;gt;K_{m_i} = \{ x_{l_q} \in L \| x_{m_i} = \arg \min_{x_{m_s} \in M}  d(x_{l_q}, x_{m_s}) \}, i=1 \dots K, K -&amp;lt;/math&amp;gt; множество искомых кластеров.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма PAM сосредоточено в стадии &#039;&#039;&#039;SWAP&#039;&#039;&#039; и состоит из вычислений значений целевой функции для различных вариантов замены текущей медоиды на новую:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;F = arg \min_{i \in M , j \in L} \sum_{y \in L \backslash \{j\}} {min (d(i,y),d(j,y))} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Если на вход алгоритма была подана не матрица расстояний, а матрица объектов с их координатами в пространстве &amp;lt;math&amp;gt;R^P&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;P&amp;lt;/math&amp;gt; будет являться макрооперацией. В качестве меры расстояния может быть использована евклидова метрика:&lt;br /&gt;
&amp;lt;math&amp;gt; d(a,b) = \sqrt{\sum_{i=1}^P (a_i-b_i)^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Псевдокод алгоритма&#039;&#039; &amp;lt;ref&amp;gt;Park H. S., Jun C. H. A simple and fast algorithm for K-medoids clustering //Expert Systems with Applications. – 2009. – Т. 36. – №. 2. – С. 3336-3341.:&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 1  функция PAM(D, k, tmax=100):&lt;br /&gt;
 2      &amp;lt;span style=&amp;quot;color:#408080&amp;quot;&amp;gt;# D - матрица расстояний, k - число кластеров, tmax - маскимальное число итераций&amp;lt;/span&amp;gt;&lt;br /&gt;
 3      выполнить фазу BUILD, получить множество метоидов M и множество не-метоидов L&lt;br /&gt;
 4      вычислить значение целевой функции F&lt;br /&gt;
 5      для t = 0..tmax-1:&lt;br /&gt;
 6          выполнить фазу SWAP, вычислить значение целевой функции F&#039;&lt;br /&gt;
 7          delta = F - F&#039;&lt;br /&gt;
 8          если delta &amp;gt; 0:&lt;br /&gt;
 9              обновить множества M и L&lt;br /&gt;
 10             F = F&#039;&lt;br /&gt;
 11         иначе:&lt;br /&gt;
 12             выйти из цикла&lt;br /&gt;
 13     вернуть М&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;N&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;BUILD&#039;&#039;&#039; каждый шаг нахождения очередного метоида имеет сложность &amp;lt;math&amp;gt;O(N^2)&amp;lt;/math&amp;gt; по количеству операций сложения вещественных чисел и по количеству операций сравнения двух вещественных чисел.&lt;br /&gt;
&amp;lt;br&amp;gt;Тогда стадия &#039;&#039;&#039;BUILD&#039;&#039;&#039; имеет сложность &amp;lt;math&amp;gt;O(K*N^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На стадии &#039;&#039;&#039;SWAP&#039;&#039;&#039; вычисление целевой функции имеет сложность &amp;lt;math&amp;gt;O(K*N^2)&amp;lt;/math&amp;gt; по количеству операций сложения вещественных чисел и по количеству операций сравнения двух вещественных чисел.&lt;br /&gt;
&lt;br /&gt;
Таким образом алгоритм &amp;lt;b&amp;gt;PAN&amp;lt;/b&amp;gt; имеет сложность &amp;lt;math&amp;gt;O(T*K*N^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Фаза BUILD&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Общий вид информационного графа для шага t представлен на рисунке 1:&lt;br /&gt;
&lt;br /&gt;
[[Файл:BUILD_2.png|thumb|center|800px|Рисунок 1. Информационный граф шага t фазы BUILD алгоритма.]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Операции&#039;&#039;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;b&amp;gt;Update&amp;lt;math&amp;gt;_M&amp;lt;/math&amp;gt;&amp;lt;/b&amp;gt; и &amp;lt;b&amp;gt;Update&amp;lt;math&amp;gt;_L&amp;lt;/math&amp;gt;&amp;lt;/b&amp;gt; - операции обновления множества метоидов и не-метоидов соответственно&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;b&amp;gt;SUM&amp;lt;/b&amp;gt; - вычисление функции ошибки, на вход подается расстояния от очередного объекта до всех остальных, а также минимальные расстояния от выбранных на данном шаге метоидов до всех остальных вершин&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;b&amp;gt;MIN&amp;lt;math&amp;gt;_s&amp;lt;/math&amp;gt;&amp;lt;/b&amp;gt; - нахождение аргумента, соответствующего минимальному значению, а также само минимальное значение&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;b&amp;gt;MIN&amp;lt;math&amp;gt;_d&amp;lt;/math&amp;gt;&amp;lt;/b&amp;gt; - нахождение минимальных расстояний от медоидов до остальных вершин, используется в операции SUM&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
Количество шагов t равно &amp;lt;b&amp;gt;K&amp;lt;/b&amp;gt;, где &amp;lt;b&amp;gt;K&amp;lt;/b&amp;gt; - число кластеров&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Фаза SWAP&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Общий вид информационного графа для итерации t представлен на рисунке 2:&lt;br /&gt;
&lt;br /&gt;
[[Файл:SWAP_2.png|thumb|center|800px|Рисунок 2. Информационный граф итерации t фазы SWAP алгоритма.]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Операции&#039;&#039;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;b&amp;gt;Update&amp;lt;math&amp;gt;_M&amp;lt;/math&amp;gt;&amp;lt;/b&amp;gt; и &amp;lt;b&amp;gt;Update&amp;lt;math&amp;gt;_L&amp;lt;/math&amp;gt;&amp;lt;/b&amp;gt; - операции обновления множества метоидов и не-метоидов соответственно&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;b&amp;gt;SUM&amp;lt;/b&amp;gt; - вычисление целевой функции&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;b&amp;gt;MIN&amp;lt;/b&amp;gt; - нахождение аргумента, соответствующего минимальному значению, а также само минимальное значение&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Пусть число кластеров равно &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt;, а число объектов равно &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;. Тогда параллельная сложность фазы &amp;lt;b&amp;gt;BUILD&amp;lt;/b&amp;gt; имеет &amp;lt;math&amp;gt;O(K*N)&amp;lt;/math&amp;gt; операций сложения и &amp;lt;math&amp;gt;O(K*N)&amp;lt;/math&amp;gt; операций сравнения двух вещественных чисел. Таким образом параллельная сложность фазы &amp;lt;b&amp;gt;BUILD&amp;lt;/b&amp;gt; равна &amp;lt;math&amp;gt;O(K*N*T)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Параллельная сложность фазы &amp;lt;b&amp;gt;SWAP&amp;lt;/b&amp;gt; имеет &amp;lt;math&amp;gt;O(K*N)&amp;lt;/math&amp;gt; операций сложения и &amp;lt;math&amp;gt;O(K*N)&amp;lt;/math&amp;gt; операций сравнения двух вещественных чисел. Параллельная сложность фазы &amp;lt;b&amp;gt;SWAP&amp;lt;/b&amp;gt; равна &amp;lt;math&amp;gt;O(K*N*T)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 Таким образом параллельная сложность алгоритма равна &amp;lt;math&amp;gt;O(K*N*T)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#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;N&amp;lt;/math&amp;gt; - количество объектов;&lt;br /&gt;
 * вектор попарных расстояний, имеющий длину &amp;lt;math&amp;gt;N*(N-1)/2&amp;lt;/math&amp;gt;, из данных чисел однозначно восстанавливается симметрическая матрица расстояний &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;&lt;br /&gt;
&#039;&#039;Объём входных данных&#039;&#039;: &amp;lt;math&amp;gt;N*(N-1)/2&amp;lt;/math&amp;gt; вещественное число и &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; целых числа.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Выходные данные&#039;&#039;:&lt;br /&gt;
 * K чисел &amp;lt;math&amp;gt;m_1, m_2, ..., m_K&amp;lt;/math&amp;gt; - индексы объектов соответствующие метоидам;&lt;br /&gt;
 * N-K чисел &amp;lt;math&amp;gt;k_1, k_2, ..., k_{N-K}&amp;lt;/math&amp;gt; - номера кластеров для каждого объекта (кроме тех, что являются метоидами);&lt;br /&gt;
&#039;&#039;Объём выходных данных&#039;&#039;: &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; целых чисел.&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]]&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Суммарный объем входных данных равен &amp;lt;math&amp;gt; O(N^2) &amp;lt;/math&amp;gt; , число операций алгоритма &#039;&#039;&#039;PAM&#039;&#039;&#039; равно &amp;lt;math&amp;gt; O(K*N^2*\Tau) &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; &amp;amp;ndash; число кластеров, &amp;lt;math&amp;gt;\Tau&amp;lt;/math&amp;gt; &amp;amp;ndash; число итераций алгоритма, &amp;lt;math&amp;gt; N &amp;lt;/math&amp;gt; - число точек. Тогда вычислительная мощность алгоритма &#039;&#039;&#039;PAM&#039;&#039;&#039; равна &amp;lt;math&amp;gt;O(K*\Tau)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;b&amp;gt;[[глоссарий#Детерминированность |&#039;&#039;Детерминированность&#039;&#039;]] и [[глоссарий#Устойчивость |&#039;&#039;Устойчивость&#039;&#039;]] &amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Алгоритм &amp;lt;i&amp;gt;PAM&amp;lt;/i&amp;gt; является итерационным, количество итераций может быть ограничено сверху, однако в общем случае не фиксируется. Из-за недетермирированности выбора элементов, на которых достигается минимум целевой функции, алгоритм не является &amp;lt;b&amp;gt;детермирированным&amp;lt;/b&amp;gt;. Однако, данный алгоритм является &amp;lt;b&amp;gt;устойчивым&amp;lt;/b&amp;gt;, поскольку не накапливает ошибки в процессе своей работы. &amp;lt;ref&amp;gt;Нейский И. М. Классификация и сравнение методов кластеризации //ББК 32.813 И 76 Составитель: ЮН Филиппович. – 2006. – С. 130.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Сильные стороны алгоритма&amp;lt;/b&amp;gt;:&lt;br /&gt;
&amp;lt;ul&amp;gt;  &lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;i&amp;gt;Меньшая чувствительность к выбросам, чем k-means&amp;lt;/i&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;i&amp;gt;Несложность реализации&amp;lt;/i&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&lt;br /&gt;
    &amp;lt;p&amp;gt;&amp;lt;i&amp;gt;Возможность распараллеливания&amp;lt;/i&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
    &amp;lt;p&amp;gt;Однако равномерная загрузка процессоров не всегда возможна.&amp;lt;/p&amp;gt;&lt;br /&gt;
  &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;Недостатки алгоритма&amp;lt;/b&amp;gt;:&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&amp;lt;i&amp;gt;Квадратичная сложность алгоритма&amp;lt;/i&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&lt;br /&gt;
    &amp;lt;p&amp;gt;&amp;lt;i&amp;gt;Количество кластеров является параметром алгоритма&amp;lt;/i&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
    &amp;lt;p&amp;gt;Во многих задачах число кластеров может быть неизвестным.&amp;lt;/p&amp;gt;&lt;br /&gt;
  &amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;&lt;br /&gt;
    &amp;lt;p&amp;gt;&amp;lt;i&amp;gt;Возможность сходимости к локальному оптимуму&amp;lt;/i&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
    &amp;lt;p&amp;gt;Оптимальное решение не гарантировано.&amp;lt;/p&amp;gt;&lt;br /&gt;
  &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
&lt;br /&gt;
Исследование проводилось на суперкомпьютере &#039;&#039;&#039;&amp;quot;Ломоносов&amp;quot;&#039;&#039;&#039; &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/lomonosov.html Аппаратные характеристики суперкомпьютера]. Алгоритм реализован с использованием технологии &#039;&#039;&#039;MPI&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Данные были сгенерированы в &#039;&#039;&#039;Matlab&#039;е&#039;&#039;&#039; случайным образом. Количество кластеров равно &#039;&#039;&#039;16&#039;&#039;&#039;, каждый кластер был промоделирован нормальным распределением с некоторыми случайными значениями среднего и среднеквадратического отклонения. Размерность данных равна &#039;&#039;&#039;2&#039;&#039;&#039;, а число точек на каждый кластер было достаточно большим для проведения экспериментов с различными значениями размерности матрицы расстояний. Пример сгенерированных данных показан на рисунке 3.&lt;br /&gt;
&lt;br /&gt;
[[Файл:16_clusters.jpg|thumb|center|512px|Рисунок 3. Пример сгенерированных данных.]]&lt;br /&gt;
&lt;br /&gt;
Измерялось &#039;&#039;&#039;время выполнения&#039;&#039;&#039; стадий &#039;&#039;&#039;BUILD&#039;&#039;&#039; и &#039;&#039;&#039;SWAP&#039;&#039;&#039;, без учета времени, потраченного на построение матрицы расстояний, а также измерялось &#039;&#039;&#039;число итераций&#039;&#039;&#039; алгоритма.&lt;br /&gt;
Были проведены эксперименты для следующих значений размерности матрицы расстояний и числа процессоров:&lt;br /&gt;
&lt;br /&gt;
 Значения размерности: [2500, 2000, 1500, 1000, 500, 200, 150, 100, 50]&lt;br /&gt;
 Значения числа процессоров: [500, 400, 256, 128, 64, 32, 16, 8, 4, 1]&lt;br /&gt;
&lt;br /&gt;
Полученные графики производительности и эффективности представлены на рисунках 4 и 5 соответственно.&lt;br /&gt;
&lt;br /&gt;
[[Файл:GFLOPS.png|thumb|center|512px|Рисунок 4. Зависимость производительности реализации параллельного алгоритма от размера матрицы и числа процессоров]]&lt;br /&gt;
[[Файл:EFF.png|thumb|center|512px|Рисунок 5. Зависимость эффективности реализации параллельного алгоритма от размера матрицы и числа процессоров.]]&lt;br /&gt;
&lt;br /&gt;
Таким образом, из полученных графиков можно сделать вывод о том, что эффективность задачи при фиксированном размере входной матрицы понижается с увеличением числа процессоров, это связано с увеличением передачи данных между процессорами. При фиксированном значениии числа процессоров эффективность увеличивается при увеличении размера входной матрицы, это в свою очередь связано с тем, что доля времени, потраченного на передачу данных между процессорами, от общего затраченного на вычисления времени уменьшается.&lt;br /&gt;
&lt;br /&gt;
В экспериментах была использована сторонняя реализация алгоритма, с небольшими изменениями она выложена в репозитории[https://denemmy@bitbucket.org/denemmy/pam.git]&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;[http://research.omicsgroup.org/index.php/ELKI ELKI] реализует несколько вариантов алгоритма кластеризации, включая алгоритм PAM. Написан на Java&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;[http://java-ml.sourceforge.net/ Java-ML]. Включает реализацию k-metoid. Написан на Java&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;[http://research.omicsgroup.org/index.php?title=Julia_language&amp;amp;action=edit&amp;amp;redlink=1 Julia] содержит реализацию k-metoid в пакете для кластеризации JuliaStats&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;[http://research.omicsgroup.org/index.php/R_(programming_language) R] включает различные варианты k-means в пакете flexclust. Алгоритм PAM реализован в пакете cluster&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;[http://research.omicsgroup.org/index.php/MATLAB MATLAB]. Реализованы PAM, CLARA и другие алгоритмы кластеризации&amp;lt;/li&amp;gt;&lt;br /&gt;
  &amp;lt;li&amp;gt;[http://research.omicsgroup.org/index.php/Python_(programming_language) Python]. Алгоритм PAM реализован как k-medoids в пакете pyclust, содержащем также различные варианты k-means&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Dexter</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%D1%8F%D0%B7%D0%B8%D0%BD%D0%B0_%D0%95%D0%BA%D0%B0%D1%82%D0%B5%D1%80%D0%B8%D0%BD%D0%B0/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BE%D0%BD%D1%86%D0%B5%D0%BF%D1%82%D1%83%D0%B0%D0%BB%D1%8C%D0%BD%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_COBWEB&amp;diff=19073</id>
		<title>Обсуждение участника:Мязина Екатерина/Алгоритм концептуальной кластеризации COBWEB</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%D1%8F%D0%B7%D0%B8%D0%BD%D0%B0_%D0%95%D0%BA%D0%B0%D1%82%D0%B5%D1%80%D0%B8%D0%BD%D0%B0/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BE%D0%BD%D1%86%D0%B5%D0%BF%D1%82%D1%83%D0%B0%D0%BB%D1%8C%D0%BD%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_COBWEB&amp;diff=19073"/>
		<updated>2016-11-24T08:43:39Z</updated>

		<summary type="html">&lt;p&gt;Dexter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;1) Во врезке сверху отсутствует информация о параллельной версии алгоритма - см. образцовую статью&lt;br /&gt;
&lt;br /&gt;
2) Нет списка литературы, ссылок на источники&lt;br /&gt;
&lt;br /&gt;
3) Пункты 2.1, 2.4 не заполнены&lt;/div&gt;</summary>
		<author><name>Dexter</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%D1%8F%D0%B7%D0%B8%D0%BD%D0%B0_%D0%95%D0%BA%D0%B0%D1%82%D0%B5%D1%80%D0%B8%D0%BD%D0%B0/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BE%D0%BD%D1%86%D0%B5%D0%BF%D1%82%D1%83%D0%B0%D0%BB%D1%8C%D0%BD%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_COBWEB&amp;diff=19072</id>
		<title>Обсуждение участника:Мязина Екатерина/Алгоритм концептуальной кластеризации COBWEB</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%D1%8F%D0%B7%D0%B8%D0%BD%D0%B0_%D0%95%D0%BA%D0%B0%D1%82%D0%B5%D1%80%D0%B8%D0%BD%D0%B0/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BE%D0%BD%D1%86%D0%B5%D0%BF%D1%82%D1%83%D0%B0%D0%BB%D1%8C%D0%BD%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_COBWEB&amp;diff=19072"/>
		<updated>2016-11-24T08:42:06Z</updated>

		<summary type="html">&lt;p&gt;Dexter: Новая страница: «1) Во врезке сверху отсутствует информация о параллельной версии алгоритма - см. образцов…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;1) Во врезке сверху отсутствует информация о параллельной версии алгоритма - см. образцовую статью&lt;/div&gt;</summary>
		<author><name>Dexter</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%A0%D1%83%D1%81%D0%BB%D0%B0%D0%BD/%D0%9F%D0%BB%D0%BE%D1%82%D0%BD%D0%BE%D1%81%D1%82%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&amp;diff=19071</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%A0%D1%83%D1%81%D0%BB%D0%B0%D0%BD/%D0%9F%D0%BB%D0%BE%D1%82%D0%BD%D0%BE%D1%81%D1%82%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&amp;diff=19071"/>
		<updated>2016-11-24T08:38:49Z</updated>

		<summary type="html">&lt;p&gt;Dexter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;1) Ссылки на источнике есть, но работы в списке не пронумерованы. Плюс сам список литературы оформлен неряшливо, со сдвигами в первых источниках&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
2) Поясните, что значит &amp;quot;плотно-достижимые&amp;quot;&lt;/div&gt;</summary>
		<author><name>Dexter</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:Avasilenko/Partitioning_Around_Medoids_(PAM)&amp;diff=19070</id>
		<title>Участник:Avasilenko/Partitioning Around Medoids (PAM)</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:Avasilenko/Partitioning_Around_Medoids_(PAM)&amp;diff=19070"/>
		<updated>2016-11-24T08:28:04Z</updated>

		<summary type="html">&lt;p&gt;Dexter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Преподаватель 1|Dexter}}&lt;br /&gt;
{{Assignment|Zhum}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Partitioning Around Medoids&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(T*kn^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n*(n-1)+2&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;k+1&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(T*kn)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(k(n-k))&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Авторы&#039;&#039;&#039;:&lt;br /&gt;
* [[Участник:Avasilenko|А.Э.Василенко]] (отвечает за программистскую составляющую);&lt;br /&gt;
* [[Участник:Anastasia|А.В.Тузикова]] (отвечает за математическую составляющую).&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;Rousseeuw P. J., Kaufman L. Finding Groups in Data. – Wiley Online Library, 1990.&amp;lt;/ref&amp;gt;. Более того - это важная часть процесса познания мира, в котором мы живем. Мы учим детей различать кошек и собак, воду и песок, мужчин и женщин путем постоянного развития и улучшения подсознательных схем классификации. Примеры есть и во взрослой жизни – в химии необходимо классифицировать соединения, в археологии – объединять находки по периодам и т.д.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Задача кластеризации&#039;&#039;&#039; - разделение множества объектов на заданное число множеств с минимизацией некоторого функционала - является популярной задачей, относится к разделу машинного обучения и находит применение в таких областях, как анализ текста, биоинформатика, интеллектуальные транспортные системы и др. &amp;lt;ref&amp;gt; Речкалов Т.В. Параллельный алгоритм кластеризации для многоядерного сопроцессора Intel Xeon Phi // Суперкомпьютерные дни в России: Труды vеждународной конференции. – М.: Изд-во МГУ, 2015, c. 532.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Существует несколько видов кластеризации&amp;lt;ref&amp;gt;Маннинг К.Д., Введение в информационный поиск: пер. с англ. / К.Д. Маннинг, П. Рагхаван, Х.Шютце - М. : Вильямс, 2011. - 528.&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;плоская кластеризация&#039;&#039; (&#039;&#039;flat clustering&#039;&#039;) - порождает совокупность кластеров, не имеющих явных взаимосвязей;&lt;br /&gt;
* &#039;&#039;иерархическая кластеризация&#039;&#039; (&#039;&#039;hierarchical clustering&#039;&#039;) - создаёт иерархию кластеров.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;PAM&#039;&#039;&#039; (&#039;&#039;&#039;Partitioning Around Medoids&#039;&#039;&#039;) - плоский алгоритм кластеризации, позволяющий выделить &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;
Модель &amp;lt;ref&amp;gt;Kaufman, L. and Rousseeuw, P.J., Clustering by means of Medoids. In: Y. Dodge and North-Holland, editor. Statistical Data Analysis Based on the L1-Norm and Related Methods. Springer US; 1987, p. 405–416.&amp;lt;/ref&amp;gt;, лежащая в основе алгоритма PAM, основана на выборе &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; объектов, являющихся характерными точками соответствующего кластера. Таким образом, кластерам сопоставляются принадлежащие им объекты, называемые &#039;&#039;&#039;медоидами&#039;&#039;&#039;, на основании которых распределяются остальные объекты по принципу наибольшего сходства. Cама модель называется моделью &#039;&#039;&#039;k-medoids&#039;&#039;&#039; (не путать с моделью &#039;&#039;k-median&#039;&#039;).&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
PAM состоит из двух фаз: &#039;&#039;&#039;BUILD&#039;&#039;&#039; и &#039;&#039;&#039;SWAP&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
*   на фазе BUILD выполняется первичная кластеризация, в ходе которой последовательно выбираются &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; объектов в качестве медоидов;&lt;br /&gt;
*   фаза SWAP представляет собой итерационный процесс, в ходе которого производятся попытки улучшить множество медоидов. Алгоритм выполняет поиск пары объектов (медоид, не-медоид), минимизирующих целевую функцию при замене, после чего обновляет множество медоидов.&lt;br /&gt;
&lt;br /&gt;
На каждой итерации алгоритма выбирается пара (медоид, не-медоид) такая, что замена медоида &amp;lt;math&amp;gt;x_{m_l}&amp;lt;/math&amp;gt; на не-медоид &amp;lt;math&amp;gt;x_{o_h}&amp;lt;/math&amp;gt; дает лучшую кластеризацию из возможных. Оценка кластеризации выполняется с помощью целевой функции, вычисляемой как сумма расстояний от каждого объекта до ближайшего медоида:&lt;br /&gt;
 &lt;br /&gt;
:&amp;lt;math&amp;gt;E = \sum_{j = 1}^n \min_{1 \leq l \leq k} \rho ( x_{m_l},x_{o_j} )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Процедура изменения множества медоидов повторяется, пока есть возможность улучшения значения целевой функции.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
 &lt;br /&gt;
&#039;&#039;Исходные данные&#039;&#039;:&lt;br /&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;x_i&amp;lt;/math&amp;gt; - кортеж, состоящий из &amp;lt;math&amp;gt; w &amp;lt;/math&amp;gt; вещественных чисел;&lt;br /&gt;
*   симметрическая матрица &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, элементы матрицы &amp;lt;math&amp;gt;d_{ij}=d(i,j)&amp;lt;/math&amp;gt; - вычисленные расстояния между объектами &amp;lt;math&amp;gt;x_i, x_j&amp;lt;/math&amp;gt;;&lt;br /&gt;
*   количество кластеров &amp;lt;math&amp;gt;k \leq n.&amp;lt;/math&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
&#039;&#039;Обозначения&#039;&#039;:&lt;br /&gt;
*   &amp;lt;math&amp;gt;M = \{ x_{m_1}, x_{m_2}, ... , x_{m_k} \} &amp;lt;/math&amp;gt; - множество медоидов, &amp;lt;math&amp;gt; M \subseteq X ;&amp;lt;/math&amp;gt;&lt;br /&gt;
*   &amp;lt;math&amp;gt;O = \{ x_{o_1}, x_{o_2}, ... , x_{o_r} \} &amp;lt;/math&amp;gt; - множество не-медоидов, &amp;lt;math&amp;gt; O \subseteq X, &amp;lt;/math&amp;gt; где &amp;lt;math&amp;gt;r=n-k;&amp;lt;/math&amp;gt;&lt;br /&gt;
*   &amp;lt;math&amp;gt;d_{ij}=\rho (x_i, x_j )&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \rho  : X \times X \rightarrow R &amp;lt;/math&amp;gt; — метрика расстояния;&lt;br /&gt;
*   &amp;lt;math&amp;gt;F_{M,O} = \sum_{j = 1}^{n} \min_{ x_{m_l} \in M} \rho ( x_{m_l},x_{o_j} )&amp;lt;/math&amp;gt; - значение целевой функции для заданных множеств &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;O;&amp;lt;/math&amp;gt;&lt;br /&gt;
*   &amp;lt;math&amp;gt;T^i&amp;lt;/math&amp;gt; - изменение целевой функции на &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-м шаге фазы SWAP.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Выходные данные&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;M = \{ x_{m_1}, x_{m_2}, ... , x_{m_k} \}&amp;lt;/math&amp;gt; - множество медоидов;&lt;br /&gt;
* &amp;lt;math&amp;gt;K_{m_i} = \{ x_{o_h} \in O \| x_{m_i} = \arg \min_{x_{m_s} \in M} \rho (x_{o_h}, x_{m_s}) \}, 1 \leq i \leq k&amp;lt;/math&amp;gt; - искомые кластеры.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Вычислительные формулы метода&#039;&#039;:&lt;br /&gt;
 &lt;br /&gt;
*   &#039;&#039;фаза BUILD&#039;&#039; (состоит из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; шагов последовательного выбора &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; медоидов):&lt;br /&gt;
**   &amp;lt;math&amp;gt;O_0 = X, M_0 = \varnothing ;&amp;lt;/math&amp;gt;&lt;br /&gt;
**   &amp;lt;math&amp;gt;x_{m_1} = \arg \min_{x_{o_h} \in O_0} \sum_{j = 1}^n \rho \left ( x_{o_h},x_j \right ), O_1 = O_0 \backslash \{x_{m_1}\}, M_1 = M_1 \cup \{x_{m_1}\} ; &amp;lt;/math&amp;gt;&lt;br /&gt;
**   &amp;lt;math&amp;gt;x_{m_2} = \arg \min_{x_{o_h} \in O_1} \sum_{j = 1}^{n} \min ( \rho ( x_{m_1},x_j ), \rho ( x_{o_h},x_j ) ), O_2 = O_1 \backslash \{x_{m_2}\}, M_2 = M_1 \cup \{x_{m_2}\} ; &amp;lt;/math&amp;gt;&lt;br /&gt;
**   &amp;lt;math&amp;gt;x_{m_3} = \arg \min_{x_{o_h} \in O_2} \sum_{j = 1}^{n} \min_{1 \leq l \leq 2} ( \rho ( x_{m_l},x_j ) , \rho ( x_{o_h},x_j ) ) , O_3 = O_2 \backslash \{x_{m_3}\}, M_3 = M_3 \cup \{x_{m_3}\} ; &amp;lt;/math&amp;gt;&lt;br /&gt;
** ...&lt;br /&gt;
**   &amp;lt;math&amp;gt;x_{m_k} = \arg \min_{x_{o_h} \in O_{k-1}} \sum_{j = 1}^{n} \min_{ x_{m_l} \in M_{k-1}} ( \rho ( x_{m_l},x_j ), \rho ( x_{o_h},x_j ) ) , O_k = O_{k-1} \backslash \{x_{m_k}\}, M_k = M_{k-1} \cup \{x_{m_k}\} ; &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;фаза SWAP&#039;&#039; (итерационный процесс):&lt;br /&gt;
** начальное приближение: &amp;lt;math&amp;gt;O_0 = O_k^{BUILD}, M_0 = M_k^{BUILD};&amp;lt;/math&amp;gt;&lt;br /&gt;
** &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-й шаг итерации:&lt;br /&gt;
*** вычисление целевой функции при оптимальной замене (замене, при которой достигается лучшая кластеризация из возможных на текущей итерации): &amp;lt;br&amp;gt;&amp;lt;math&amp;gt;F^i = \min_{x_{m_s} \in M_{i-1} , x_{o_h} \in O_{i-1}} \sum_{j = 1}^{n} \min_{ x_{m_l} \in M_{i-1} \backslash \{x_{m_s}\} } ( \rho ( x_{m_l},x_j ), \rho ( x_{o_h},x_j) ); &amp;lt;/math&amp;gt;&lt;br /&gt;
*** определение пары (медоид, не-медоид), на которой достигается оптимальная замена: &amp;lt;br&amp;gt;&amp;lt;math&amp;gt; (x_{m_s}, x_{o_h}) = \arg F^i; &amp;lt;/math&amp;gt;&lt;br /&gt;
*** проверка критерия останова;&lt;br /&gt;
*** изменение множеств в соответствии с выбранной парой &amp;lt;math&amp;gt; (x_{m_s}, x_{o_h}):&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&amp;lt;math&amp;gt;M_i = M_{i-1} \backslash \{x_{m_s}\} \cup \{x_{o_h}\} , O_i = O_{i-1} \cup \{x_{m_s}\} \backslash \{x_{o_h}\} ;&amp;lt;/math&amp;gt;&lt;br /&gt;
** критерий останова:&lt;br /&gt;
*** &amp;lt;math&amp;gt;T^i = F^{i-1} - F^{i} \leq 0 .&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вычислительное ядро алгоритма PAM на этапе BUILD&#039;&#039;&#039; состоит из многочисленных вычислений значений целевой функции при различных вариантах выбора дополнительного медоида (шаг алгоритма &amp;lt;math&amp;gt;1 \leq i \leq k&amp;lt;/math&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;F^i = \min_{x_{o_h} \in O_{i-1}} \sum_{j = 1}^{n} \min_{ x_{m_l} \in M_{i-1}} ( \rho ( x_{m_l},x_j ), \rho ( x_{o_h},x_j ) ) = \min_{x_{o_h} \in O_{i-1}} \sum_{j = 1}^{n} \overline{MIN}_{i, x_{o_h}}^{(j)},&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где:&lt;br /&gt;
* &amp;lt;math&amp;gt;\overline{MIN}_{1, x_{o_h} \in O_0} = \{ \rho (x_{o_h}, x_j ) \| 1 \leq j \leq n \};&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;\overline{MIN}_{i, x_{o_h} \in O_{i-1}} = \{ \min ( \overline{MIN}_{i-1, x_{m_{i-1}}}^{(j)}, \rho (x_{o_h}, x_j) ) \| 1 \leq j \leq n \}, \forall i: 1 &amp;lt; i \leq k.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С каждой итерацией количество вариантов выбора дополнительных медоидов уменьшается на единицу, таким образом, на &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-м шаге целевую функцию нужно вычислить лишь &amp;lt;math&amp;gt;|O_{i-1}| = n-i+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;
* таким образом, на каждой последующей итерации можно использовать величину, вычисленную на предыдущем шаге, что позволяет сократить число вычислений минимумов.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вычислительное ядро алгоритма PAM на этапе SWAP&#039;&#039;&#039; состоит из многочисленных вычислений значений целевой функции при различных вариантах замены некоторого существующего медоида на элемент из числа не-медоидов. &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-я итерация фазы SWAP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;F^i = \min_{x_{m_s} \in M_{i-1} , x_{o_h} \in O_{i-1}} \sum_{j = 1}^{n} \min_{ x_{m_l} \in M_{i-1} \backslash \{x_{m_s}\} } ( \rho ( x_{m_l},x_j ), \rho ( x_{o_h},x_j) ) =&amp;lt;/math&amp;gt;&amp;lt;br&amp;gt;&amp;lt;math&amp;gt;= \min_{x_{m_s} \in M_{i-1} } \min_{x_{o_h} \in O_{i-1}} \sum_{j = 1}^{n} \min ( \min_{ x_{m_l} \in M_{i-1} \backslash \{x_{m_s}\} } ( \rho ( x_{m_l},x_j )) , \rho ( x_{o_h},x_j) )&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;x_{o_h}&amp;lt;/math&amp;gt;, для которых вычисляется &amp;lt;math&amp;gt;\sum_{j = 1}^{n} \min (a, b)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;a&amp;lt;/math&amp;gt; есть &amp;lt;math&amp;gt; \min_{ x_{m_l} \in M_{i-1} \backslash \{x_{m_s}\} } ( \rho ( x_{m_l},x_j )),&amp;lt;/math&amp;gt; и является инвариантом по отношению к &amp;lt;math&amp;gt;\min_{x_{o_h} \in O_{i-1}} \sum_{j = 1}^{n} \min ( \min_{ x_{m_l} \in M_{i-1} \backslash \{x_{m_s}\} } ( \rho ( x_{m_l},x_j )) , \rho ( x_{o_h},x_j) ),&amp;lt;/math&amp;gt; что позволяет предвычислить элемент &amp;lt;math&amp;gt;a.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Опишем макрооперации алгоритма&#039;&#039;:&lt;br /&gt;
* в случае если алгоритму PAM на вход подаётся набор точек с их координатами в пространстве &amp;lt;math&amp;gt;R^w,&amp;lt;/math&amp;gt; то необходимо вычислить матрицу расстояний. Для этого может быть использована, например, евклидова метрика:&lt;br /&gt;
*: &amp;lt;math&amp;gt;\rho (p,q)=\sqrt{(p_1-q_1)^2+(p_2-q_2)^2+\dots+(p_w-q_w)^2} = \sqrt{\sum_{j=1}^w (p_j-q_j)^2} &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;p, q \in R^w;&amp;lt;/math&amp;gt;&lt;br /&gt;
* нахождение минимального среди значений, принимаемых некоторой функцией &amp;lt;math&amp;gt;value,&amp;lt;/math&amp;gt; определённой на дискретном множестве &amp;lt;math&amp;gt;Y=\{y_i\}, \, i = \overline{(1,r)}:&amp;lt;/math&amp;gt;&lt;br /&gt;
*: &amp;lt;math&amp;gt;minimum_{y \in Y } (value (y)) = \min \Bigg(value(y_1), \min \bigg(value(y_2), \min \Big(\dots , \min(value(y_{r-1}), value(y_{r})) ... \Big) \bigg)\Bigg);&amp;lt;/math&amp;gt;&lt;br /&gt;
* вычисление вектора инвариантов, используемых при оптимизации фазы SWAP (см. вычислительное ядро алгоритма):&lt;br /&gt;
*: &amp;lt;math&amp;gt;\overline{a} = \{ minimum_{ x_{m_l} \in M_{i-1} \backslash \{x_{m_s}\} } ( \rho ( x_{m_l}, x_j ) ) \| 1 \leq j \leq n \},&amp;lt;/math&amp;gt; где &amp;lt;math&amp;gt;i - &amp;lt;/math&amp;gt;номер итерации;&lt;br /&gt;
* вычисление вектора расстояний от каждой точки заданного множества &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; до ближайшего медоида из множества &amp;lt;math&amp;gt;M_{i-1} \backslash \{x_{m_s}\},&amp;lt;/math&amp;gt; где &amp;lt;math&amp;gt;i - &amp;lt;/math&amp;gt;номер итерации фазы SWAP: &lt;br /&gt;
*: &amp;lt;math&amp;gt;\overline{b} = \{ \min (\overline{a}^{(j)}, \rho ( x_{o_p}, x_j )) \| 1 \leq j \leq n \};&amp;lt;/math&amp;gt;&lt;br /&gt;
* сложение компонент вектора: &amp;lt;math&amp;gt;S = \sum_{j = 1}^{n} \overline{f}^{(j)}.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Макроструктура вычислительного ядра алгоритма PAM&#039;&#039; может быть выражена через макрооперации следующим образом:&lt;br /&gt;
* для ядра фазы BUILD:&lt;br /&gt;
*::: &amp;lt;math&amp;gt;F^i = minimum_{ x_{o_h} \in O_{i-1} } ( S \, ( \overline{f} (x_{o_h}) )),&amp;lt;/math&amp;gt;&lt;br /&gt;
*::: &amp;lt;math&amp;gt;\overline{f} = \{ \min \,( \overline{MIN}_{i, x_{o_h}}^{(j)}, \rho (x_{o_h}, x_j)) \| 1 \leq j \leq n \}, &amp;lt;/math&amp;gt; где&lt;br /&gt;
*# &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; вычисляется &amp;lt;math&amp;gt;n-i+1&amp;lt;/math&amp;gt; раз;&lt;br /&gt;
*# &amp;lt;math&amp;gt;minimum&amp;lt;/math&amp;gt; находится &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; раз при вычислении наилучшего значения целевой функции на текущей итерации.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* для ядра фазы SWAP:&lt;br /&gt;
*::: &amp;lt;math&amp;gt;F^i = minimum_{ x_{m_s} \in M_{i-1} , x_{o_h} \in O_{i-1} } ( S \, ( \overline{b} \, ( x_{o_h}, \overline{a} \, (x_{m_s}) ) )),&amp;lt;/math&amp;gt; где:&lt;br /&gt;
*# &amp;lt;math&amp;gt;minimum&amp;lt;/math&amp;gt; находится &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; раз  в процессе вычисления макрооперации &amp;lt;math&amp;gt;\overline {a};&amp;lt;/math&amp;gt;&lt;br /&gt;
*# &amp;lt;math&amp;gt;\overline {a}&amp;lt;/math&amp;gt; вычисляется &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; раз и использует вычисленные на шаге 1 минимальные значения;&lt;br /&gt;
*# &amp;lt;math&amp;gt;\overline {b}&amp;lt;/math&amp;gt; вычисляется &amp;lt;math&amp;gt;k(n-k)&amp;lt;/math&amp;gt; раз и использует вычисленные на шаге 2 значения &amp;lt;math&amp;gt;\overline {a};&amp;lt;/math&amp;gt;&lt;br /&gt;
*# &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; вычисляется &amp;lt;math&amp;gt;k(n-k)&amp;lt;/math&amp;gt; раз и использует вычисленные на шаге 3 значения &amp;lt;math&amp;gt;\overline {b};&amp;lt;/math&amp;gt;&lt;br /&gt;
*# &amp;lt;math&amp;gt;minimum&amp;lt;/math&amp;gt; находится &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; раз при вычислении наилучшего значения целевой функции на текущей итерации.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Псевдокод алгоритма&#039;&#039;:&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;D&amp;lt;/math&amp;gt;, количество кластеров &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;&lt;br /&gt;
 &#039;&#039;&#039;Выход&#039;&#039;&#039; : Множество медоидов &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;&lt;br /&gt;
 0  Если на вход было подано множество объектов, необходимо предварительно вычислить матрицу расстояний;&lt;br /&gt;
 1  Инициализация множеств &amp;lt;math&amp;gt;M := \varnothing, O := X;&amp;lt;/math&amp;gt;&lt;br /&gt;
 &amp;amp;nbsp;&lt;br /&gt;
    // фаза BUILD&lt;br /&gt;
 2  &#039;&#039;&#039;for (int i := 1; i &amp;lt;= k; i++)&#039;&#039;&#039; {&lt;br /&gt;
        // Найти &amp;lt;math&amp;gt;x_{m_i}:&amp;lt;/math&amp;gt;&lt;br /&gt;
        {&lt;br /&gt;
 3          Для всех &amp;lt;math&amp;gt;x_{o_h} \in O&amp;lt;/math&amp;gt; вычислить &amp;lt;math&amp;gt;F_{M \cup \{x_{o_h}\}, O \backslash \{x_{o_h}\}};&amp;lt;/math&amp;gt;&lt;br /&gt;
 4          Положить &amp;lt;math&amp;gt;x_{m_i}&amp;lt;/math&amp;gt; равным &amp;lt;math&amp;gt;x_{o_h}&amp;lt;/math&amp;gt;, соответствующему минимальному из вычисленных &amp;lt;math&amp;gt;F;&amp;lt;/math&amp;gt;&lt;br /&gt;
        }&lt;br /&gt;
 5      Обновить множества &amp;lt;math&amp;gt;M := M \cup \{x_{m_i}\}, O := O \backslash \{x_{m_i}\};&amp;lt;/math&amp;gt;&lt;br /&gt;
    }&lt;br /&gt;
    // фаза SWAP&lt;br /&gt;
 6  &#039;&#039;&#039;while (1)&#039;&#039;&#039; {&lt;br /&gt;
        // Найти пару &amp;lt;math&amp;gt;(x_{m_s}, x_{o_h}),&amp;lt;/math&amp;gt; на которой достигается оптимальная замена:&lt;br /&gt;
        {&lt;br /&gt;
 7          Для всех &amp;lt;math&amp;gt;x_{m_i} \in M, x_{o_j} \in O&amp;lt;/math&amp;gt; вычислить &amp;lt;math&amp;gt;F^i;&amp;lt;/math&amp;gt; // вычисление проводить с учётом приведённой ранее оптимизации (см. 1.3 [[#Вычислительное ядро алгоритма|Вычислительное ядро алгоритма]]);&lt;br /&gt;
 8          Положить пару &amp;lt;math&amp;gt;(x_{m_s}, x_{o_h})&amp;lt;/math&amp;gt; равной паре &amp;lt;math&amp;gt;(x_{m_i}, x_{o_j})&amp;lt;/math&amp;gt;, соответствующей минимальному из вычисленных &amp;lt;math&amp;gt;F;&amp;lt;/math&amp;gt;&lt;br /&gt;
        }&lt;br /&gt;
 9      Вычислить &amp;lt;math&amp;gt;T^i;&amp;lt;/math&amp;gt; // критерий останова (см. 1.2 [[#Математическое описание алгоритма|Математическое описание алгоритма]])&lt;br /&gt;
 10     &#039;&#039;&#039;if&#039;&#039;&#039; &amp;lt;math&amp;gt;(T^i &amp;gt; 0)&amp;lt;/math&amp;gt; {&lt;br /&gt;
 11         Обновить множества &amp;lt;math&amp;gt;M := M \backslash \{x_{m_s}\} \cup \{x_{o_h}\}, O := O \cup \{x_{m_s}\} \backslash \{x_{o_h}\};&amp;lt;/math&amp;gt;&lt;br /&gt;
 12     } &#039;&#039;&#039;else&#039;&#039;&#039; {&lt;br /&gt;
 13         &#039;&#039;&#039;break&#039;&#039;&#039;;&lt;br /&gt;
        }&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Оптимизации&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Предвычисление матрицы расстояний&#039;&#039;&#039;. Необходимо предварительно вычислить матрицу расстояний и сохранить её в памяти, так как в ходе вычисления алгоритма многократно используются расстояния между элементами, а вычисление каждого из них является ресурсоёмкой операцией из нескольких умножений и одного извлечения квадратного корня.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Минимизация кеш-промахов&#039;&#039;&#039;. Матрица расстояний, к которой постоянно выполняется доступ на чтение для вычисления минимумов и их суммирования, должна храниться в памяти как матрица размера &amp;lt;math&amp;gt;n*n&amp;lt;/math&amp;gt;, несмотря на то, что она симметрическая и достаточно хранить лишь половину (элементы над или под главной диагональю). Данная оптимизация потребует использования в 2 раза большего количества памяти для хранения расстояний (а это является главным расходом памяти программы, так как все остальные используемые данные являются временными (локальными для каждой операции) и представляют из себя несколько векторов длинной &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; элементов). Однако так как в данном алгоритме доступ к матрице осуществляется построчно (в  [[#Вычислительное ядро алгоритма|вычислительном ядре алгоритма]] поэлементно ищутся  минимумы 2-х векторов, после чего все они складываются), то в этом случае из матрицы можно будет читать данные по строкам подряд, что снижает количество кеш-промахов. Использование только половины матрицы приводит к частым промахам в кеше в связи с необходимостью загрузки части векторов по строкам, а части - по столбцам.&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;\frac{n*(n-1)}{2}&amp;lt;/math&amp;gt; операций вычисления расстояний;&lt;br /&gt;
* сложность каждой операции вычисления расстояния (для случая использования Евклидовой метрики) равна &amp;lt;math&amp;gt;2*w-1&amp;lt;/math&amp;gt; операций сложения и вычитания, &amp;lt;math&amp;gt;w&amp;lt;/math&amp;gt; операций возведения в квадрат (умножения) и &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; операции извлечения квадратного корня.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
На основании формулы из описания &#039;&#039;&#039;вычислительного ядра фазы BUILD&#039;&#039;&#039; определим сложность выполнения всего этапа.&lt;br /&gt;
&lt;br /&gt;
Обозначим:&lt;br /&gt;
*&amp;lt;math&amp;gt;summs&amp;lt;/math&amp;gt; - операция сложения двух вещественных чисел;&lt;br /&gt;
*&amp;lt;math&amp;gt;mins&amp;lt;/math&amp;gt; - операция нахождения минимума для двух вещественных чисел.&lt;br /&gt;
&lt;br /&gt;
Тогда, количество операций равно:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;S = ( ( (n-1) summs ) * (n-1+1) + (n-1+1-1)mins) + \sum_{i = 2}^{k} ( ( (1 mins)*(n-1) + (n-1) summs ) * (n-i+1) + (n-i+1-1)mins) \Rightarrow&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\Rightarrow S =&lt;br /&gt;
  \begin{cases}&lt;br /&gt;
    S(mins) = ( ( 0 ) * (n-1+1) + (n-1+1-1)mins) + \sum_{i = 2}^{k} ( ( (1 mins)*(n-1)) * (n-i+1) + (n-i+1-1)mins ) &amp;amp; \quad\\&lt;br /&gt;
    S(summs) = \sum_{i = 1}^{k} ( ( (n-1) summs ) * (n-i+1) ) &amp;amp; \quad\\&lt;br /&gt;
  \end{cases}&lt;br /&gt;
=&lt;br /&gt;
&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
: &amp;lt;math&amp;gt;&lt;br /&gt;
=&lt;br /&gt;
  \begin{cases}&lt;br /&gt;
    S(mins) = n^2(k-1) - \frac{1}{2}(nk^2 - nk) + n - k &amp;amp; \quad\\&lt;br /&gt;
    S(summs) = n^2k - \frac{1}{2}(nk^2 + nk - k^2 + k ) &amp;amp; \quad\\&lt;br /&gt;
  \end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Таким образом, сложность фазы BUILD есть &amp;lt;math&amp;gt;O(kn^2)&amp;lt;/math&amp;gt; как по количеству найденных минимумов, так и по количеству операций сложения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
На основании формулы из описания &#039;&#039;&#039;вычислительного ядра фазы SWAP&#039;&#039;&#039; определим сложность вычисления целевой функции &amp;lt;math&amp;gt;F^i&amp;lt;/math&amp;gt; с использованием оптимизации процесса нахождения минимума (см. раздел [[#Вычислительное ядро алгоритма|Вычислительное ядро алгоритма]]). Количество операций равно:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;S = ( ( (1 mins)*(n-1) + (n-1) summs )*(n-k) + n*((k-1-1) mins) )*k \Rightarrow&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\Rightarrow S =&lt;br /&gt;
  \begin{cases}&lt;br /&gt;
    S(mins) = ( ((1 mins)*(n-1) )*(n-k) + n*((k-1-1) mins) )*k = kn^2 - 3nk + k^2 &amp;amp; \quad\\&lt;br /&gt;
    S(summs) = ( ( (n-1) summs )*(n-k) )*k = (n-1)(n-k)k &amp;amp; \quad\\&lt;br /&gt;
  \end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Таким образом, сложность одной итерации фазы SWAP есть &amp;lt;math&amp;gt;O(kn^2)&amp;lt;/math&amp;gt; как по количеству найденных минимумов, так и по количеству операция сложения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Полученные оценки позволяют говорить о том, что PAM относится к алгоритмам &#039;&#039;&#039;с квадратичной сложностью&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Основная вычислительная сложность алгоритма PAM приходится на фазу SWAP, т.к. сложность одной её итерации сопоставима со сложностью всей фазы BUILD, однако SWAP может содержать в себе огромное число итераций.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
&lt;br /&gt;
==== Информационный граф фазы BUILD ====&lt;br /&gt;
 &lt;br /&gt;
Опишем граф фазы BUILD как аналитически, так и в виде рисунка.&lt;br /&gt;
 &lt;br /&gt;
&#039;&#039;Граф состоит из шести групп вершин&#039;&#039;:&lt;br /&gt;
 &lt;br /&gt;
# Операция M, соответствующая &#039;&#039;&#039;первой&#039;&#039;&#039; группе вершин, осуществляет изменение множества медоидов:&lt;br /&gt;
#:: &amp;lt;math&amp;gt;M_{It} = M_{It-1} \cup \overline{x}_{m_{It}}, &amp;lt;/math&amp;gt; где &amp;lt;math&amp;gt;\overline{x}_{m_{It}} = \overline{x}_{o_{It}}.&amp;lt;/math&amp;gt;&lt;br /&gt;
#: Единственная координата &amp;lt;math&amp;gt;It&amp;lt;/math&amp;gt; (номер итерации), соответствующая каждой из вершин, меняется в диапазоне &amp;lt;math&amp;gt;[1; k],&amp;lt;/math&amp;gt; принимая все целочисленные значения.&lt;br /&gt;
#: Аргументами операции являются:&lt;br /&gt;
#:* &amp;lt;math&amp;gt;\overline{x}_{o_{It}}&amp;lt;/math&amp;gt; - результат срабатывания операции, соответствующей вершине из пятой группы с координатой &amp;lt;math&amp;gt;It,&amp;lt;/math&amp;gt;&lt;br /&gt;
#:* &amp;lt;math&amp;gt;M_{It-1}&amp;lt;/math&amp;gt; - множество медоидов:&lt;br /&gt;
#:** при &amp;lt;math&amp;gt;It = 1 &amp;lt;/math&amp;gt; - входное данное алгоритма;&lt;br /&gt;
#:** при &amp;lt;math&amp;gt;1&amp;lt; It \leq k &amp;lt;/math&amp;gt; -  результат срабатывания операции, соответствующей вершине из первой группы с координатой &amp;lt;math&amp;gt;It-1.&amp;lt;/math&amp;gt;&lt;br /&gt;
#: Результат срабатывания операции является:&lt;br /&gt;
#:* при &amp;lt;math&amp;gt;It &amp;lt; k &amp;lt;/math&amp;gt; - &#039;&#039;промежуточным данным&#039;&#039; алгоритма;&lt;br /&gt;
#:* при &amp;lt;math&amp;gt;It = k &amp;lt;/math&amp;gt; - &#039;&#039;выходным данным&#039;&#039; фазы BUILD.&lt;br /&gt;
#:&lt;br /&gt;
#: &amp;lt;br&amp;gt;&lt;br /&gt;
#:&lt;br /&gt;
# Операция O, соответствующая &#039;&#039;&#039;второй&#039;&#039;&#039; группе вершин, осуществляет изменение множества не-медоидов:&lt;br /&gt;
#:: &amp;lt;math&amp;gt;O_{It} = O_{It-1} \backslash \overline{x}_{o_{It}}.&amp;lt;/math&amp;gt;&lt;br /&gt;
#: Единственная координата &amp;lt;math&amp;gt;It&amp;lt;/math&amp;gt;, соответствующая каждой из вершин, меняется в диапазоне &amp;lt;math&amp;gt;[1; k],&amp;lt;/math&amp;gt; принимая все целочисленные значения.&lt;br /&gt;
#: Аргументами операции являются:&lt;br /&gt;
#:* &amp;lt;math&amp;gt;\overline{x}_{o_{It}}&amp;lt;/math&amp;gt; - результат срабатывания операции, соответствующей вершине из пятой группы с координатой &amp;lt;math&amp;gt;It,&amp;lt;/math&amp;gt;&lt;br /&gt;
#:* &amp;lt;math&amp;gt;O_{It-1}&amp;lt;/math&amp;gt; - множество не-медоидов:&lt;br /&gt;
#:** при &amp;lt;math&amp;gt;It = 1 &amp;lt;/math&amp;gt; - входное данное алгоритма;&lt;br /&gt;
#:** при &amp;lt;math&amp;gt;1&amp;lt; It \leq k &amp;lt;/math&amp;gt; -  результат срабатывания операции, соответствующей вершине из второй группы с координатой &amp;lt;math&amp;gt;It-1.&amp;lt;/math&amp;gt;&lt;br /&gt;
#: Результат срабатывания операции является:&lt;br /&gt;
#:* при &amp;lt;math&amp;gt;It &amp;lt; k &amp;lt;/math&amp;gt; - &#039;&#039;промежуточным данным&#039;&#039; алгоритма;&lt;br /&gt;
#:* при &amp;lt;math&amp;gt;It = k &amp;lt;/math&amp;gt; - &#039;&#039;выходным данным&#039;&#039; фазы BUILD.&lt;br /&gt;
#:&lt;br /&gt;
#: &amp;lt;br&amp;gt;&lt;br /&gt;
#:&lt;br /&gt;
# Операция, соответствующая &#039;&#039;&#039;третьей&#039;&#039;&#039; группе вершин, выглядит следующим образом:&lt;br /&gt;
#:: &amp;lt;math&amp;gt;\overline{c}=\overline{c}_{x_{o_p} } =  \begin{cases} \{ \rho (x_{o_p}, x_j ) \| 1 \leq j \leq n \}, It=1 &amp;amp; \quad\\ \{ \min ( \overline{MIN}^{(j)}, \rho (x_{o_p}, x_j) ) \| 1 \leq j \leq n \}, 1&amp;lt;It \leq k &amp;amp; \quad\\  \end{cases} .&amp;lt;/math&amp;gt;&lt;br /&gt;
#: Координаты вершин:&lt;br /&gt;
#:* &amp;lt;math&amp;gt;It&amp;lt;/math&amp;gt; - меняется в диапазоне &amp;lt;math&amp;gt;[1; k],&amp;lt;/math&amp;gt; принимая все целочисленные значения;&lt;br /&gt;
#:* &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; - меняется в диапазоне &amp;lt;math&amp;gt;[1; n-It+1],&amp;lt;/math&amp;gt; принимая все целочисленные значения.&lt;br /&gt;
#: Аргументами операции являются:&lt;br /&gt;
#:* при &amp;lt;math&amp;gt;It = 1:&amp;lt;/math&amp;gt;&lt;br /&gt;
#:** &amp;lt;math&amp;gt;\overline{x}_{o_p}&amp;lt;/math&amp;gt; - входное данное алгоритма;&lt;br /&gt;
#:* при &amp;lt;math&amp;gt;1 &amp;lt; It \leq k:&amp;lt;/math&amp;gt;&lt;br /&gt;
#:**&amp;lt;math&amp;gt;\overline{x}_{o_p}&amp;lt;/math&amp;gt; - результат срабатывания операции, соответствующей вершине из второй группы с координатой &amp;lt;math&amp;gt;It-1;&amp;lt;/math&amp;gt;&lt;br /&gt;
#:**&amp;lt;math&amp;gt;\overline{MIN}&amp;lt;/math&amp;gt; - результат срабатывания операции, соответствующей вершине из шестой группы с координатой &amp;lt;math&amp;gt;It-1.&amp;lt;/math&amp;gt;&lt;br /&gt;
#: Результат срабатывания операции является &#039;&#039;промежуточным данным&#039;&#039; алгоритма.&lt;br /&gt;
#:&lt;br /&gt;
#: &amp;lt;br&amp;gt;&lt;br /&gt;
#:&lt;br /&gt;
# Операция S, соответствующая &#039;&#039;&#039;четвертой&#039;&#039;&#039; группе вершин, выглядит следующим образом:&lt;br /&gt;
#:: &amp;lt;math&amp;gt;S = \sum_{j = 1}^{n} \overline {c}^{(j)}.&amp;lt;/math&amp;gt;&lt;br /&gt;
#: Координаты вершин:&lt;br /&gt;
#:* &amp;lt;math&amp;gt;It&amp;lt;/math&amp;gt; - меняется в диапазоне &amp;lt;math&amp;gt;[1; k],&amp;lt;/math&amp;gt; принимая все целочисленные значения;&lt;br /&gt;
#:* &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; - меняется в диапазоне &amp;lt;math&amp;gt;[1; n-It+1],&amp;lt;/math&amp;gt; принимая все целочисленные значения.&lt;br /&gt;
#: Аргументами операции являются:&lt;br /&gt;
#:* &amp;lt;math&amp;gt;\overline{c}_{ x_{o_p} }&amp;lt;/math&amp;gt; - результат срабатывания операции, соответствующей вершине из третьей группы с координатами &amp;lt;math&amp;gt; It, p.&amp;lt;/math&amp;gt;&lt;br /&gt;
#: Результат срабатывания операции является &#039;&#039;промежуточным данным&#039;&#039; алгоритма.&lt;br /&gt;
#:&lt;br /&gt;
#: &amp;lt;br&amp;gt;&lt;br /&gt;
#:&lt;br /&gt;
# Операция M1, соответствующая &#039;&#039;&#039;пятой&#039;&#039;&#039; группе вершин, выглядит следующим образом:&lt;br /&gt;
#:: &amp;lt;math&amp;gt;M1 = (F^{It}; x_{o_{It}}),&amp;lt;/math&amp;gt; где &amp;lt;math&amp;gt; \begin{cases}&lt;br /&gt;
F^{It} = \min_{x_{o_p} \in O_{It-1}} S &amp;amp; \quad\\&lt;br /&gt;
x_{o_{It}} = \arg F^{It} &amp;amp; \quad\\&lt;br /&gt;
\end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
#: Координаты вершин:&lt;br /&gt;
#:* &amp;lt;math&amp;gt;It&amp;lt;/math&amp;gt; - меняется в диапазоне &amp;lt;math&amp;gt;[1; k],&amp;lt;/math&amp;gt; принимая все целочисленные значения.&lt;br /&gt;
#: Аргументами операции являются:&lt;br /&gt;
#:* &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; - результаты срабатывания операций, соответствующих вершинам из четвертой группы с первой координатой &amp;lt;math&amp;gt;It,&amp;lt;/math&amp;gt; всего &amp;lt;math&amp;gt;n-It+1&amp;lt;/math&amp;gt; величина.&lt;br /&gt;
#: Результат срабатывания операции является:&lt;br /&gt;
#:* при &amp;lt;math&amp;gt;It &amp;lt; k &amp;lt;/math&amp;gt; - &#039;&#039;промежуточным данным&#039;&#039; алгоритма;&lt;br /&gt;
#:* при &amp;lt;math&amp;gt;It = k &amp;lt;/math&amp;gt; - &#039;&#039;выходным данным&#039;&#039; фазы BUILD.&lt;br /&gt;
#:&lt;br /&gt;
#: &amp;lt;br&amp;gt;&lt;br /&gt;
#:&lt;br /&gt;
# Операция MIN, соответствующая &#039;&#039;&#039;шестой&#039;&#039;&#039; группе вершин, выглядит следующим образом:&lt;br /&gt;
#:: &amp;lt;math&amp;gt;\overline{MIN}=\overline{MIN}_{It,x_{m_{It}} } =  \begin{cases}&lt;br /&gt;
\{ \rho (x_{m_{It}            }, x_j ) \| 1 \leq j \leq n \}, It=1 &amp;amp; \quad\\&lt;br /&gt;
\{ \min ( \overline{MIN}^{(j)}, \rho (x_{m_{It}}, x_j) ) \| 1 \leq j \leq n \}, 1&amp;lt;It \leq k &amp;amp; \quad\\&lt;br /&gt;
 \end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
#: Координаты вершин:&lt;br /&gt;
#:* &amp;lt;math&amp;gt;It&amp;lt;/math&amp;gt; - меняется в диапазоне &amp;lt;math&amp;gt;[1; k-1],&amp;lt;/math&amp;gt; принимая все целочисленные значения.&lt;br /&gt;
#: Аргументами операции являются:&lt;br /&gt;
#:* &amp;lt;math&amp;gt;\overline{MIN}_{It-1,x_{m_{It-1}}} &amp;lt;/math&amp;gt; - результат срабатывания операции, соответствующей вершине из шестой группы с координатой &amp;lt;math&amp;gt;It-1;&amp;lt;/math&amp;gt;&lt;br /&gt;
#:* &amp;lt;math&amp;gt;x_{m_{It}} =  x_{o_{It}} &amp;lt;/math&amp;gt; - результат срабатывания операции, соответствующей вершине из пятой группы с координатой &amp;lt;math&amp;gt;It.&amp;lt;/math&amp;gt;&lt;br /&gt;
#: Результат срабатывания операции является &#039;&#039;промежуточным данным&#039;&#039; алгоритма.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Описанный граф в общем случае представлен на Рис.1, отображен шаг с номером &amp;lt;math&amp;gt;It, 1&amp;lt;It&amp;lt;k&amp;lt;/math&amp;gt; фазы BUILD.&lt;br /&gt;
Обозначения:&lt;br /&gt;
# вершины первой группы обозначены фиолетовым цветом и подписаны как &amp;lt;math&amp;gt;M;&amp;lt;/math&amp;gt;&lt;br /&gt;
# вершины  второй группы обозначены синим цветом и подписаны как &amp;lt;math&amp;gt;O;&amp;lt;/math&amp;gt;&lt;br /&gt;
# вершины третьей группы обозначены жёлтым цветом и подписаны как &amp;lt;math&amp;gt;\overline{c}_{x_{o_p} };&amp;lt;/math&amp;gt;&lt;br /&gt;
# вершины четвертой группы обозначены серым цветом и подписаны как &amp;lt;math&amp;gt;S;&amp;lt;/math&amp;gt;&lt;br /&gt;
# вершины пятой группы обозначены зеленым цветом и подписаны как &amp;lt;math&amp;gt;M1;&amp;lt;/math&amp;gt;&lt;br /&gt;
# вершины шестой группы обозначены красным цветом и подписаны как &amp;lt;math&amp;gt;MIN;&amp;lt;/math&amp;gt;&lt;br /&gt;
# синим дугам сопоставлены метки, отражающие данные, используемые в соответствующих жёлтых вершинах.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[file:Pam build 1.png|thumb|center|800px|Рисунок 1. Граф фазы BUILD алгоритма.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
На Рис.2 представлен граф фазы BUILD для случая &amp;lt;math&amp;gt;n=6, k=3.&amp;lt;/math&amp;gt; Вершины, соответствующие операциям, получающим входные данные и производящим выходные данные, увеличены и выделены толстыми границами.&lt;br /&gt;
&lt;br /&gt;
[[file:Pam build 2.png|thumb|center|1100px|Рисунок 2. Граф фазы BUILD алгоритма для n = 6, k = 3. ]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Информационный граф фазы SWAP ====&lt;br /&gt;
 &lt;br /&gt;
Опишем граф фазы SWAP как аналитически, так и в виде рисунка.&lt;br /&gt;
 &lt;br /&gt;
&#039;&#039;Граф состоит из семи групп вершин&#039;&#039;:&lt;br /&gt;
 &lt;br /&gt;
# Операция M, соответствующая &#039;&#039;&#039;первой&#039;&#039;&#039; группе вершин, осуществляет изменение множества медоидов.&lt;br /&gt;
#: Единственная координата &amp;lt;math&amp;gt;It&amp;lt;/math&amp;gt; (номер итерации), соответствующая каждой из вершин, меняется в диапазоне &amp;lt;math&amp;gt;[1; T),&amp;lt;/math&amp;gt; принимая все целочисленные значения, где:&lt;br /&gt;
#:: &amp;lt;math&amp;gt;T\in \N&amp;lt;/math&amp;gt; - количество выполнений фазы SWAP во время работы алгоритма PAM.&lt;br /&gt;
#: Аргументами операции являются:&lt;br /&gt;
#:* результат срабатывания операции, соответствующей вершине из седьмой группы с координатой &amp;lt;math&amp;gt;It,&amp;lt;/math&amp;gt;&lt;br /&gt;
#:* &amp;lt;math&amp;gt;M_{It-1}&amp;lt;/math&amp;gt; - множество медоидов:&lt;br /&gt;
#:** при &amp;lt;math&amp;gt;It = 1 &amp;lt;/math&amp;gt; - результат выполнения фазы BUILD;&lt;br /&gt;
#:** при &amp;lt;math&amp;gt;1&amp;lt; It &amp;lt; T &amp;lt;/math&amp;gt; -  результат срабатывания операции, соответствующей вершине из первой группы с координатой &amp;lt;math&amp;gt;It-1.&amp;lt;/math&amp;gt;&lt;br /&gt;
#: Результат срабатывания операции является:&lt;br /&gt;
#:* при &amp;lt;math&amp;gt;It &amp;lt; T -1 &amp;lt;/math&amp;gt; - &#039;&#039;промежуточным данным&#039;&#039; алгоритма;&lt;br /&gt;
#:* при &amp;lt;math&amp;gt;It = T - 1&amp;lt;/math&amp;gt; - &#039;&#039;выходным данным&#039;&#039; фазы SWAP.&lt;br /&gt;
#:&lt;br /&gt;
#: &amp;lt;br&amp;gt;&lt;br /&gt;
#:&lt;br /&gt;
# Операция O, соответствующая &#039;&#039;&#039;второй&#039;&#039;&#039; группе вершин, осуществляет изменение множества не-медоидов.&lt;br /&gt;
#: Единственная координата &amp;lt;math&amp;gt;It&amp;lt;/math&amp;gt;, соответствующая каждой из вершин, меняется в диапазоне &amp;lt;math&amp;gt;[1; T),&amp;lt;/math&amp;gt; принимая все целочисленные значения, где:&lt;br /&gt;
#:: &amp;lt;math&amp;gt;T\in \N&amp;lt;/math&amp;gt; - количество выполнений фазы SWAP во время работы алгоритма PAM.&lt;br /&gt;
#: Аргументами операции являются:&lt;br /&gt;
#:* результат срабатывания операции, соответствующей вершине из седьмой группы с координатой &amp;lt;math&amp;gt;It,&amp;lt;/math&amp;gt;&lt;br /&gt;
#:* &amp;lt;math&amp;gt;O_{It-1}&amp;lt;/math&amp;gt; - множество не-медоидов:&lt;br /&gt;
#:** при &amp;lt;math&amp;gt;It = 1 &amp;lt;/math&amp;gt; - результат выполнения фазы BUILD;&lt;br /&gt;
#:** при &amp;lt;math&amp;gt;1&amp;lt; It &amp;lt; T &amp;lt;/math&amp;gt; -  результат срабатывания операции, соответствующей вершине из второй группы с координатой &amp;lt;math&amp;gt;It-1.&amp;lt;/math&amp;gt;&lt;br /&gt;
#: Результат срабатывания операции является &#039;&#039;промежуточным данным&#039;&#039; алгоритма.&lt;br /&gt;
#:&lt;br /&gt;
#: &amp;lt;br&amp;gt;&lt;br /&gt;
#:&lt;br /&gt;
# Операция, соответствующая &#039;&#039;&#039;третьей&#039;&#039;&#039; группе вершин, выглядит следующим образом:&lt;br /&gt;
#:: &amp;lt;math&amp;gt;\overline{a}=\overline{a}_{x_{m_i} } = \{ \min_{ x_{m_l} \in M  \backslash \{x_{m_i}\} }  \rho ( x_{m_l},x_j ) \| 1 \leq j \leq n \}.&amp;lt;/math&amp;gt;&lt;br /&gt;
#: Координаты вершин:&lt;br /&gt;
#:* &amp;lt;math&amp;gt;It&amp;lt;/math&amp;gt; - меняется в диапазоне &amp;lt;math&amp;gt;[1; T],&amp;lt;/math&amp;gt; принимая все целочисленные значения;&lt;br /&gt;
#:* &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - меняется в диапазоне &amp;lt;math&amp;gt;[1; k],&amp;lt;/math&amp;gt; принимая все целочисленные значения.&lt;br /&gt;
#: Аргументом операции является &amp;lt;math&amp;gt;\overline{x}_{m_i}:&amp;lt;/math&amp;gt;&lt;br /&gt;
#:* при &amp;lt;math&amp;gt;It = 1&amp;lt;/math&amp;gt; - результат выполнения фазы BUILD;&lt;br /&gt;
#:* при &amp;lt;math&amp;gt;It &amp;gt; 1&amp;lt;/math&amp;gt; - результат срабатывания операции, соответствующей вершине из первой группы с координатой &amp;lt;math&amp;gt;It-1.&amp;lt;/math&amp;gt;&lt;br /&gt;
#: Результат срабатывания операции является &#039;&#039;промежуточным данным&#039;&#039; алгоритма.&lt;br /&gt;
#:&lt;br /&gt;
#: &amp;lt;br&amp;gt;&lt;br /&gt;
#:&lt;br /&gt;
# Операция, соответствующая &#039;&#039;&#039;четвертой&#039;&#039;&#039; группе вершин, выглядит следующим образом:&lt;br /&gt;
#:: &amp;lt;math&amp;gt;\overline{b}=\overline{b}_{x_{m_i} x_{o_p} } =  \{ \min (\overline{a}_{ x_{m_i}}^{(j)}, \rho ( x_{o_p},x_j )) \| 1 \leq j \leq n \}.&amp;lt;/math&amp;gt;&lt;br /&gt;
#: Координаты вершин:&lt;br /&gt;
#:* &amp;lt;math&amp;gt;It&amp;lt;/math&amp;gt; - меняется в диапазоне &amp;lt;math&amp;gt;[1; T],&amp;lt;/math&amp;gt; принимая все целочисленные значения;&lt;br /&gt;
#:* &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - меняется в диапазоне &amp;lt;math&amp;gt;[1; k],&amp;lt;/math&amp;gt; принимая все целочисленные значения;&lt;br /&gt;
#:* &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; - меняется в диапазоне &amp;lt;math&amp;gt;[1; n-k],&amp;lt;/math&amp;gt; принимая все целочисленные значения.&lt;br /&gt;
#: Аргументами операции являются:&lt;br /&gt;
#:* &amp;lt;math&amp;gt;\overline{x}_{o_p}:&amp;lt;/math&amp;gt;&lt;br /&gt;
#:** при &amp;lt;math&amp;gt;It = 1&amp;lt;/math&amp;gt; - результат выполнения фазы BUILD;&lt;br /&gt;
#:** при &amp;lt;math&amp;gt;It &amp;gt; 1&amp;lt;/math&amp;gt; - результат срабатывания операции, соответствующей вершине из второй группы с координатой &amp;lt;math&amp;gt;It-1&amp;lt;/math&amp;gt;&lt;br /&gt;
#:* &amp;lt;math&amp;gt;\overline{a}_{x_{m_i}}&amp;lt;/math&amp;gt; - результат срабатывания операции, соответствующей вершине из третьей группы с координатами &amp;lt;math&amp;gt;It, i.&amp;lt;/math&amp;gt;&lt;br /&gt;
#: Результат срабатывания операции является &#039;&#039;промежуточным данным&#039;&#039; алгоритма.&lt;br /&gt;
#:&lt;br /&gt;
#: &amp;lt;br&amp;gt;&lt;br /&gt;
#:&lt;br /&gt;
# Операция S, соответствующая &#039;&#039;&#039;пятой&#039;&#039;&#039; группе вершин, выглядит следующим образом:&lt;br /&gt;
#:: &amp;lt;math&amp;gt;S = \sum_{j = 1}^{n} \overline {b}^{(j)}.&amp;lt;/math&amp;gt;&lt;br /&gt;
#: Координаты вершин:&lt;br /&gt;
#:* &amp;lt;math&amp;gt;It&amp;lt;/math&amp;gt; - меняется в диапазоне &amp;lt;math&amp;gt;[1; T],&amp;lt;/math&amp;gt; принимая все целочисленные значения;&lt;br /&gt;
#:* &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - меняется в диапазоне &amp;lt;math&amp;gt;[1; k],&amp;lt;/math&amp;gt; принимая все целочисленные значения;&lt;br /&gt;
#:* &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; - меняется в диапазоне &amp;lt;math&amp;gt;[1; n-k],&amp;lt;/math&amp;gt; принимая все целочисленные значения.&lt;br /&gt;
#: Аргументами операции являются:&lt;br /&gt;
#:* &amp;lt;math&amp;gt;\overline{b}_{x_{m_i} x_{o_p} }&amp;lt;/math&amp;gt; - результат срабатывания операции, соответствующей вершине из четвертой группы с координатами &amp;lt;math&amp;gt;It, i, p.&amp;lt;/math&amp;gt;&lt;br /&gt;
#: Результат срабатывания операции является &#039;&#039;промежуточным данным&#039;&#039; алгоритма.&lt;br /&gt;
#:&lt;br /&gt;
#: &amp;lt;br&amp;gt;&lt;br /&gt;
#:&lt;br /&gt;
# Операция M1, соответствующая &#039;&#039;&#039;шестой&#039;&#039;&#039; группе вершин, выглядит следующим образом:&lt;br /&gt;
#:: &amp;lt;math&amp;gt;M1 = (F_{x_{o_p}}^{It}; x_{o_p}),&amp;lt;/math&amp;gt; где &amp;lt;math&amp;gt; \begin{cases}&lt;br /&gt;
F_{x_{o_p}}^{It} = \min_{x_{o_p} \in O} S &amp;amp; \quad\\&lt;br /&gt;
x_{o_p} = \arg F_{x_{o_p}}^{It} &amp;amp; \quad\\&lt;br /&gt;
\end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
#: Координаты вершин:&lt;br /&gt;
#:* &amp;lt;math&amp;gt;It&amp;lt;/math&amp;gt; - меняется в диапазоне &amp;lt;math&amp;gt;[1; T],&amp;lt;/math&amp;gt; принимая все целочисленные значения;&lt;br /&gt;
#:* &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - меняется в диапазоне &amp;lt;math&amp;gt;[1; k],&amp;lt;/math&amp;gt; принимая все целочисленные значения.&lt;br /&gt;
#: Аргументами операции являются:&lt;br /&gt;
#:* &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; - результаты срабатывания операций, соответствующих вершинам из пятой группы с первыми двумя координатами &amp;lt;math&amp;gt;It, i,&amp;lt;/math&amp;gt; всего &amp;lt;math&amp;gt;n-k&amp;lt;/math&amp;gt; величин.&lt;br /&gt;
#: Результат срабатывания операции является &#039;&#039;промежуточным данным&#039;&#039; алгоритма.&lt;br /&gt;
#:&lt;br /&gt;
#: &amp;lt;br&amp;gt;&lt;br /&gt;
#:&lt;br /&gt;
# Операция M2, соответствующая &#039;&#039;&#039;седьмой&#039;&#039;&#039; группе вершин, выглядит следующим образом:&lt;br /&gt;
#:: &amp;lt;math&amp;gt;M2 = (F_{x_{o_p}, x_{m_i}}^{It}; x_{m_i}; x_{o_p}),&amp;lt;/math&amp;gt; где &amp;lt;math&amp;gt;\begin{cases}&lt;br /&gt;
F_{x_{o_p}, x_{m_i}}^{It} = \min (\min_{x_{m_i} \in M} (F_{x_{o_p}}^{It}), M2_{It-1}) &amp;amp; \quad\\&lt;br /&gt;
x_{m_i} = \arg \min_{x_{m_i} \in M} M1 &amp;amp; \quad\\&lt;br /&gt;
\end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
#: Координаты вершин:&lt;br /&gt;
#:* &amp;lt;math&amp;gt;It&amp;lt;/math&amp;gt; - меняется в диапазоне &amp;lt;math&amp;gt;[1; T],&amp;lt;/math&amp;gt; принимая все целочисленные значения.&lt;br /&gt;
#: Аргументами операции являются:&lt;br /&gt;
#:* &amp;lt;math&amp;gt;M1 = (F_{x_{o_p}}^{It}; x_{o_p})&amp;lt;/math&amp;gt; - результаты срабатывания операций, соответствующих вершинам из шестой группы с координатами &amp;lt;math&amp;gt;It, i,&amp;lt;/math&amp;gt; всего &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; величин;&lt;br /&gt;
#:* &amp;lt;math&amp;gt;M2_{It-1}:&amp;lt;/math&amp;gt;&lt;br /&gt;
#:** при &amp;lt;math&amp;gt;It = 1&amp;lt;/math&amp;gt; - результат выполнения фазы BUILD;&lt;br /&gt;
#:** при &amp;lt;math&amp;gt;It &amp;gt; 1&amp;lt;/math&amp;gt; - результаты срабатывания операции, соответствующей вершине из седьмой группы с координатой &amp;lt;math&amp;gt;It-1;&amp;lt;/math&amp;gt;&lt;br /&gt;
#: Результат срабатывания операции является:&lt;br /&gt;
#:* при &amp;lt;math&amp;gt;It &amp;lt; T&amp;lt;/math&amp;gt; - &#039;&#039;промежуточным данным&#039;&#039; алгоритма;&lt;br /&gt;
#:* при &amp;lt;math&amp;gt;It = T&amp;lt;/math&amp;gt; - &#039;&#039;выходным данным&#039;&#039; фазы SWAP.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Описанный граф в общем случае представлен на Рис.3, отображена одна итерация фазы SWAP.&lt;br /&gt;
Обозначения:&lt;br /&gt;
# вершины первой группы обозначены фиолетовым цветом и подписаны как &amp;lt;math&amp;gt;M;&amp;lt;/math&amp;gt;&lt;br /&gt;
# вершины второй группы обозначены синим цветом и подписаны как &amp;lt;math&amp;gt;O;&amp;lt;/math&amp;gt;&lt;br /&gt;
# вершины третьей группы обозначены желтым цветом и подписаны как &amp;lt;math&amp;gt;\overline{a}_{x_{m_i} };&amp;lt;/math&amp;gt;&lt;br /&gt;
# вершины четвертой группы обозначены оранжевым цветом и подписаны как &amp;lt;math&amp;gt;\overline{b}_{x_{m_i o_p} };&amp;lt;/math&amp;gt;&lt;br /&gt;
# вершины пятой группы обозначены серым цветом и подписаны как &amp;lt;math&amp;gt;S;&amp;lt;/math&amp;gt;&lt;br /&gt;
# вершины шестой группы обозначены зеленым цветом и подписаны как &amp;lt;math&amp;gt;M1;&amp;lt;/math&amp;gt;&lt;br /&gt;
# вершины седьмой группы обозначены красным цветом и подписаны как &amp;lt;math&amp;gt;M2;&amp;lt;/math&amp;gt;&lt;br /&gt;
# синим дугам сопоставлены метки, отражающие данные, используемые в соответствующих оранжевых вершинах;&lt;br /&gt;
# фиолетовым дугам сопоставлены метки, отражающие данные, используемые в соответствующих жёлтых вершинах.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[file:Pam swap 1.png|thumb|center|1100px|Рисунок 3. Граф фазы SWAP алгоритма.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
На Рис.4 представлен граф фазы SWAP для случая &amp;lt;math&amp;gt;n=6, k=2, T=3.&amp;lt;/math&amp;gt; Вершины, соответствующие операциям, получающим входные данные и производящим выходные данные, увеличены и выделены толстыми границами.&lt;br /&gt;
&lt;br /&gt;
[[file:Pam swap 2.png|thumb|center|1100px|Рисунок 4. Граф фазы SWAP алгоритма для n = 6, k = 2, T = 3.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
При параллельной реализации алгоритма PAM будем рассматривать параллельные варианты фазы BUILD и SWAP ([[#Возможная параллельная реализация алгоритма PAM|возможная параллельная реализация]]). Покажем, что сложность фазы BUILD сопоставима со сложностью одной итерации фазы SWAP.&lt;br /&gt;
&lt;br /&gt;
Оценки последовательной сложности фаз BUILD и SWAP приведены в параграфе &amp;quot;[[#Последовательная сложность алгоритма|Последовательная сложность алгоритма]]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Ресурс параллелизма фазы BUILD ====&lt;br /&gt;
&lt;br /&gt;
Для решения задачи кластеризации методом PAM в параллельном варианте фазы BUILD в предположении доступности неограниченного числа процессов для одной итерации необходимо выполнить:&lt;br /&gt;
*  1 ярус с нахождением &amp;lt;math&amp;gt;\overline{c}:&amp;lt;/math&amp;gt;&lt;br /&gt;
** &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; операций нахождения минимального из двух элементов при &amp;lt;math&amp;gt;It &amp;gt; 1&amp;lt;/math&amp;gt;;&lt;br /&gt;
* 1 ярус с нахождением суммы &amp;lt;math&amp;gt;S:&amp;lt;/math&amp;gt;&lt;br /&gt;
** &amp;lt;math&amp;gt;n-1&amp;lt;/math&amp;gt; операцию сложения;&lt;br /&gt;
* 1 ярус с нахождением значений элемента &amp;lt;math&amp;gt;M1:&amp;lt;/math&amp;gt;&lt;br /&gt;
** &amp;lt;math&amp;gt;n-It&amp;lt;/math&amp;gt; операций нахождения минимального из двух элементов;&lt;br /&gt;
* 1 ярус с нахождением минимального элемента &amp;lt;math&amp;gt;\overline{MIN}:&amp;lt;/math&amp;gt;&lt;br /&gt;
** &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; операций нахождения минимального из двух элементов при &amp;lt;math&amp;gt;It&amp;gt;1;&amp;lt;/math&amp;gt;&lt;br /&gt;
* 1 ярус с изменением множеств медоидов и не-медоидов (не выполняются операции рассматриваемых типов).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Таким образом, параллельная сложность одного шага фазы BUILD равна: &lt;br /&gt;
* &amp;lt;math&amp;gt;n-1&amp;lt;/math&amp;gt; операция сложения;&lt;br /&gt;
* &amp;lt;math&amp;gt;n-It&amp;lt;/math&amp;gt; операций нахождения минимального из двух элементов при &amp;lt;math&amp;gt;It=1;&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;3n-It&amp;lt;/math&amp;gt; операций нахождения минимального из двух элементов при &amp;lt;math&amp;gt;It&amp;gt;1.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Параллельная сложность фазы BUILD при числе кластеров &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; равна: &lt;br /&gt;
* &amp;lt;math&amp;gt;kn-k&amp;lt;/math&amp;gt; операция сложения;&lt;br /&gt;
* &amp;lt;math&amp;gt;3kn - 2n - \frac{1}{2}k^2 - \frac{1}{2}k&amp;lt;/math&amp;gt; операций нахождения минимального из двух элементов.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В параллельном варианте, по сравнению с последовательным, при &amp;lt;math&amp;gt;k, n \to \infty&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;O(kn)&amp;lt;/math&amp;gt; против &amp;lt;math&amp;gt;O(kn^2).&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Соотношение количества сложений и взятий минимума для фазы BUILD является постоянным и стремится к &amp;lt;math&amp;gt;3,&amp;lt;/math&amp;gt; при &amp;lt;math&amp;gt;k, n \to \infty.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Максимальная ширина яруса достигается при вычислении &amp;lt;math&amp;gt;\overline {c}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; и равна &amp;lt;math&amp;gt;n-It+1&amp;lt;/math&amp;gt; для шага &amp;lt;math&amp;gt;It&amp;lt;/math&amp;gt; фазы BUILD. Максимальная ширина яруса при рассмотрении всей фазы есть &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; и достигается на первом шаге.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Ресурс параллелизма фазы SWAP ====&lt;br /&gt;
&lt;br /&gt;
Для решения задачи кластеризации методом PAM в параллельном варианте фазы SWAP в предположении доступности неограниченного числа процессов для одной итерации необходимо выполнить:&lt;br /&gt;
* 1 ярус с нахождением &amp;lt;math&amp;gt;\overline {a}:&amp;lt;/math&amp;gt;&lt;br /&gt;
** &amp;lt;math&amp;gt;n(k-1)&amp;lt;/math&amp;gt; операций нахождения минимального из двух элементов;&lt;br /&gt;
* 1 ярус с нахождением &amp;lt;math&amp;gt;\overline {b}:&amp;lt;/math&amp;gt;&lt;br /&gt;
** &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; операций нахождения минимального из двух элементов;&lt;br /&gt;
* 1 ярус с нахождением суммы &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;:&lt;br /&gt;
** &amp;lt;math&amp;gt;n-1&amp;lt;/math&amp;gt; операцию сложения;&lt;br /&gt;
* 1 ярус с нахождением минимального элемента &#039;первого&#039; вида &amp;lt;math&amp;gt;(M1 = \min_{x_{o_p} \in O} S):&amp;lt;/math&amp;gt;&lt;br /&gt;
** &amp;lt;math&amp;gt;n-k-1&amp;lt;/math&amp;gt; операцию нахождения минимального из двух элементов;&lt;br /&gt;
* 1 ярус с нахождением минимального элемента &#039;второго&#039; вида &amp;lt;math&amp;gt;(M2 = \min_{x_{m_i} \in M} M1):&amp;lt;/math&amp;gt;&lt;br /&gt;
** &amp;lt;math&amp;gt;k-1&amp;lt;/math&amp;gt; операцию нахождения минимального из двух элементов;&lt;br /&gt;
* 1 ярус с изменением множеств медоидов и не-медоидов (не выполняются операции рассматриваемых типов).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Таким образом, параллельная сложность одной итерации фазы SWAP равна:&lt;br /&gt;
* &amp;lt;math&amp;gt;n-1&amp;lt;/math&amp;gt; - по количеству операций сложения;&lt;br /&gt;
* &amp;lt;math&amp;gt;kn + n - 2&amp;lt;/math&amp;gt; - по количеству операций нахождений минимума для двух чисел.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В параллельном варианте, по сравнению с последовательным, при &amp;lt;math&amp;gt;k, n \to \infty&amp;lt;/math&amp;gt; количество операций на один порядок меньше по параметру &amp;lt;math&amp;gt;n:&amp;lt;/math&amp;gt;&lt;br /&gt;
: &amp;lt;math&amp;gt;O(kn)&amp;lt;/math&amp;gt; против &amp;lt;math&amp;gt;O(kn^2).&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Соотношение количества сложений и взятий минимума для одной итерации фазы SWAP является постоянным и равным &amp;lt;math&amp;gt;k,&amp;lt;/math&amp;gt; при &amp;lt;math&amp;gt;n \to \infty&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Максимальная ширина яруса достигается при вычислении &amp;lt;math&amp;gt;\overline {b}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; и равна &amp;lt;math&amp;gt;k(n-k).&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
При использовании выбранной модели, в предположении доступности неограниченного числа вычислителей, фаза BUILD при &amp;lt;math&amp;gt;n \to \infty&amp;lt;/math&amp;gt; требует большего количества операций суммирования на порядок &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;, по сравнению с одной итерацией фазы SWAP. В свою очередь, количество операций подсчёта минимума ассимптотически эквивалентны.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Входные данные&#039;&#039;:&lt;br /&gt;
* число &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - количество точек упорядоченного множества &amp;lt;math&amp;gt;X;&amp;lt;/math&amp;gt;&lt;br /&gt;
* число &amp;lt;math&amp;gt;k&amp;lt;/math&amp;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;X&amp;lt;/math&amp;gt; за исключением расстояний вида &amp;lt;math&amp;gt;\rho (x, x)=0, x \in X;&amp;lt;/math&amp;gt;&lt;br /&gt;
&#039;&#039;Объём входных данных&#039;&#039;: &amp;lt;math&amp;gt;n(n-1)&amp;lt;/math&amp;gt; вещественное число и &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; целых числа.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Структура хранения данных&#039;&#039;:&lt;br /&gt;
* сразу после считывания входных данных составляется квадратная симметрическая матрица &amp;lt;math&amp;gt;D^{n * n}&amp;lt;/math&amp;gt;, у которой каждый элемент &amp;lt;math&amp;gt;d_{ij}&amp;lt;/math&amp;gt; является вещественным числом - расстоянием &amp;lt;math&amp;gt;\rho (x_i, x_j);&amp;lt;/math&amp;gt;&lt;br /&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;X&amp;lt;/math&amp;gt;, аналогичный массив &amp;lt;math&amp;gt;n-k&amp;lt;/math&amp;gt; целых чисел создаётся для множества не-медоидов &amp;lt;math&amp;gt;O;&amp;lt;/math&amp;gt;&lt;br /&gt;
* для пересылки данных, как правило, используется тройка &amp;lt;math&amp;gt;(F_{x_{m_s}, x_{o_h}}^{i_j}; x_{m_s}; x_{o_h})&amp;lt;/math&amp;gt; или пара &amp;lt;math&amp;gt;(F_{x_{o_h}}^{i_j}; x_{o_h}),&amp;lt;/math&amp;gt; где:&lt;br /&gt;
** &amp;lt;math&amp;gt;x_{m_s}&amp;lt;/math&amp;gt; - целое число, обозначающее порядковый номер элемента множества &amp;lt;math&amp;gt;X;&amp;lt;/math&amp;gt;&lt;br /&gt;
** &amp;lt;math&amp;gt;x_{o_h}&amp;lt;/math&amp;gt; - целое число, обозначающее порядковый номер элемента множества &amp;lt;math&amp;gt;X;&amp;lt;/math&amp;gt;&lt;br /&gt;
** &amp;lt;math&amp;gt;F_{x_{m_s}, x_{o_h}}^{i_j}&amp;lt;/math&amp;gt; - вещественное число, равное минимальному значению целевой функции, вычисленному в текущем контексте.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Выходные данные&#039;&#039;:&lt;br /&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;
* &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; вещественное число, являющееся значением целевой функции.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Объём выходных данных&#039;&#039;:&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;  вещественное.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Соотношение последовательной и параллельной сложности алгоритма является &#039;&#039;линейным&#039;&#039; и равным &amp;lt;math&amp;gt;n.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Вычислительная мощность&#039;&#039; последовательного алгоритма, как отношение числа операций к суммарному объему входных и выходных данных, равна &amp;lt;math&amp;gt;O(T*k).&amp;lt;/math&amp;gt;&lt;br /&gt;
Вычислительная мощность параллельного алгоритма равна &amp;lt;math&amp;gt;O(T*\frac{k}{n}).&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм PAM является &#039;&#039;менее чувствительным&#039;&#039; к выбросам данных, чем алгоритм k-средних. Это связано с использованием медоидов, менее подверженных влиянию таких данных.&amp;lt;ref&amp;gt; Егоров А. В., Куприянова Н. И. Особенности методов кластеризации данных // Известия Южного федерального университета. Технические науки. –2011. T. 124, № 11. –С. 174-177.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Фиксированный способ выбора начальных приближений позволяет говорить о воспроизводимости полученных результатов для последовательной реализации. Для параллельной работы алгоритма подобная воспроизводимость отсутствует, так как из-за &#039;&#039;недетерминированности&#039;&#039; выбора элементов, на которых достигается минимальное значение целевой функции для каждой итерации, итоговое множество медоидов и, следовательно, значение целевой функции может меняться.&lt;br /&gt;
&lt;br /&gt;
Алгоритм PAM &#039;&#039;конечен&#039;&#039;, так как:&lt;br /&gt;
* количество операций фазы BUILD конечно;&lt;br /&gt;
* значение целевой фукнции неотрицательно и на каждой итерации фазы SWAP строго уменьшается.&lt;br /&gt;
&lt;br /&gt;
Одно из преимуществ алгоритма PAM заключается в том, что он может работать с любой матрицей различий. В данном случае принципиальное отличие от матрицы расстояний заключается в том, что для матрицы различий может не выполняться неравенство треугольника, так как в основе её построения не обязательно используется метрика.&lt;br /&gt;
&lt;br /&gt;
Основные операция алгоритма PAM: сложение и нахождение минимума. Операция взятия минимума не подвержена процессу накопления ошибки. На каждой итерации алгоритма сложение производится над значениями, взятыми непосредственно из исходных данных. Таким образом, алгоритм PAM не накапливает ошибок в процессе своей работы и является &#039;&#039;устойчивым&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
При &amp;lt;math&amp;gt;k(n-k) \, \bmod \, p \neq 0&amp;lt;/math&amp;gt; отсутствует возможность равномерно распределить задачи рассчёта &amp;lt;math&amp;gt;\overline{b}&amp;lt;/math&amp;gt; между процессами. Кроме того, если &amp;lt;math&amp;gt;k \, \bmod \, p \neq 0&amp;lt;/math&amp;gt;, то после их распределения для некоторых процессов окажется необходимым вычислить несколько соседних значений &amp;lt;math&amp;gt;\overline{a}.&amp;lt;/math&amp;gt; Таким образом, &#039;&#039;равномерная&#039;&#039; загрузка процессов &#039;&#039;не всегда возможна&#039;&#039;. Помимо этого, агрегирование данных с целью вычисления глобального минимума приводит к простою незадействованных процессов.&lt;br /&gt;
&lt;br /&gt;
Как и большинство алгоритмов кластеризации, PAM может сходиться к некоторому &#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;
==== Возможная параллельная реализация алгоритма PAM ====&lt;br /&gt;
&lt;br /&gt;
Необходимость уменьшения времени решения задачи приводит к потребности в создании паралельной реализации алгоритма. В дальнейшем будем придерживаться следующих допущений:&lt;br /&gt;
* возможно использование &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; процессов;&lt;br /&gt;
* не нарушая общности суждений, множества &amp;lt;math&amp;gt;M, O&amp;lt;/math&amp;gt; - упорядоченны.&lt;br /&gt;
&lt;br /&gt;
Приведённые далее возможные схемы для параллельных реализаций фазы BUILD и фазы SWAP основаны на максимально равномерном распределении задач между процессами.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Возможная параллельная реализация фазы BUILD =====&lt;br /&gt;
&lt;br /&gt;
Главная задача заключается в распараллеливании многочисленных вычислений целевой функции на каждой итерации фазы BUILD:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;F^i = \min_{x_{o_h} \in O_{i-1}} F_{x_{o_h}}^i,&amp;lt;/math&amp;gt; где &amp;lt;math&amp;gt;F_{x_{o_h}}^i = \sum_{j = 1}^{n} \overline{MIN}_{i, x_{o_h}}^{(j)},&amp;lt;/math&amp;gt; где&lt;br /&gt;
: &amp;lt;math&amp;gt;\overline{MIN}_{1, x_{o_h} \in O_0} = \{ \rho (x_{o_h}, x_j ) \| 1 \leq j \leq n \};&amp;lt;/math&amp;gt;&lt;br /&gt;
: &amp;lt;math&amp;gt;\overline{MIN}_{i, x_{o_h} \in O_{i-1}} = \{ \min ( \overline{MIN}_{i-1, x_{m_{i-1}}}^{(j)}, \rho (x_{o_h}, x_j) ) \| 1 \leq j \leq n \}, \forall i: 1 &amp;lt; i \leq k.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Схема реализации&#039;&#039;: &amp;lt;br&amp;gt;(далее &amp;lt;math&amp;gt;0 &amp;lt; i \leq k &amp;lt;/math&amp;gt; - номер текущей итерации)&lt;br /&gt;
# для каждого процесса с номером &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(0 \leq j &amp;lt; p):&amp;lt;/math&amp;gt;&lt;br /&gt;
## положим:&lt;br /&gt;
##: &amp;lt;math&amp;gt;pos = p-(n-i+1) \, \bmod \, p;&amp;lt;/math&amp;gt;&lt;br /&gt;
## на каждой итерации процессу необходимо вычислить &amp;lt;math&amp;gt;r_j&amp;lt;/math&amp;gt; значений целевой функции для соответствующих ему элементов &amp;lt;math&amp;gt;x_{o_h}, ..., x_{o_{h+(r_j-1)}}:&amp;lt;/math&amp;gt;&lt;br /&gt;
##: &amp;lt;math&amp;gt; r_j = \begin{cases}&lt;br /&gt;
    \lfloor \frac{n-i+1}{p} \rfloor , 0 \leq j &amp;lt; pos &amp;amp; \quad\\&lt;br /&gt;
    \lceil \frac{n-i+1}{p} \rceil , pos  \leq j &amp;amp; \quad\\&lt;br /&gt;
  \end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
##: &amp;lt;math&amp;gt;h = \begin{cases}&lt;br /&gt;
    r_j*j , 0 \leq j &amp;lt; pos &amp;amp; \quad\\&lt;br /&gt;
    (r_j-1)*pos + (j-pos)*r_j , pos  \leq j &amp;amp; \quad\\&lt;br /&gt;
  \end{cases}&amp;lt;/math&amp;gt; - порядковый номер &amp;lt;math&amp;gt;x_{o_h};&amp;lt;/math&amp;gt;&lt;br /&gt;
#:&lt;br /&gt;
#:&lt;br /&gt;
# каждому процессу с номером &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(0 \leq j &amp;lt; p):&amp;lt;/math&amp;gt;&lt;br /&gt;
## найти минимум среди значений целевой функции &amp;lt;math&amp;gt;F_{x_{o_h}}^i&amp;lt;/math&amp;gt; для каждого из значений параметра &amp;lt;math&amp;gt;x_{o_h};&amp;lt;/math&amp;gt; &lt;br /&gt;
##* в данном случае может быть использована оптимизация, описанная в [[#Вычислительное ядро алгоритма|вычислительном ядре алгоритма]];&lt;br /&gt;
## для процессов с номером &amp;lt;math&amp;gt;j \neq 0&amp;lt;/math&amp;gt; переслать процессу с номером &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt; пару &amp;lt;math&amp;gt;(x_{o_h}, F_{x_{o_h}}^i)&amp;lt;/math&amp;gt; для всех обработанных &amp;lt;math&amp;gt;x_{o_h};&amp;lt;/math&amp;gt;&lt;br /&gt;
#:&lt;br /&gt;
#:&lt;br /&gt;
# для процесса с номером &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt;:&lt;br /&gt;
## принять пары от процессов &amp;lt;math&amp;gt;(0, p-1],&amp;lt;/math&amp;gt; в ответ на шаг 2.2;&lt;br /&gt;
## найти &amp;lt;math&amp;gt;x_{o_h},&amp;lt;/math&amp;gt; для которого целевая функция принимает минимальное значение, и положить &amp;lt;math&amp;gt;x_{m_i}:=x_{o_h};&amp;lt;/math&amp;gt;&lt;br /&gt;
## вычислить &amp;lt;math&amp;gt;\overline{MIN}_{i, x_{m_i}}&amp;lt;/math&amp;gt;;&lt;br /&gt;
## разослать пару &amp;lt;math&amp;gt;(x_{m_i}, \overline{MIN}_{i, x_{m_i}})&amp;lt;/math&amp;gt; при помощи широковещательной рассылки;&lt;br /&gt;
#:&lt;br /&gt;
#:&lt;br /&gt;
# для каждого процесса с номером &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(0 \leq j &amp;lt; p):&amp;lt;/math&amp;gt;&lt;br /&gt;
## принять пару &amp;lt;math&amp;gt;(x_{m_i}, \overline{MIN}_{i, x_{m_i}})&amp;lt;/math&amp;gt; в ответ на шаг 3.4;&lt;br /&gt;
## скорректировать локальные копии множеств &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt;, изменив принадлежность вектора &amp;lt;math&amp;gt;x_{m_i}&amp;lt;/math&amp;gt;, а также обновить хранимое значение вектора &amp;lt;math&amp;gt;\overline{MIN}&amp;lt;/math&amp;gt; для подготовки к следующей итерации;&lt;br /&gt;
## перейти к шагу 2.1.&lt;br /&gt;
#:&lt;br /&gt;
#:&lt;br /&gt;
После завершения &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; шагов фазы BUILD, множества &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; (одинаковые для каждого процесса согласно приведенной схеме), а так же значение целевой функции являются выходными данными фазы BUILD.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Возможная параллельная реализация фазы SWAP =====&lt;br /&gt;
&lt;br /&gt;
Главная задача заключается в распараллеливании многократного вычисления целевой функции на каждой итерации фазы SWAP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;F^i = \min_{x_{m_s} \in M_{i-1} } \min_{x_{o_h} \in O_{i-1}} \sum_{j = 1}^{n} \min ( \min_{ x_{m_l} \in M_{i-1} \backslash \{x_{m_s}\} } ( \rho ( x_{m_l},x_j )) , \rho ( x_{o_h},x_j) )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Схема реализации&#039;&#039;: &amp;lt;br&amp;gt;(далее &amp;lt;math&amp;gt;i \in \N&amp;lt;/math&amp;gt; - номер текущей итерации)&lt;br /&gt;
# для каждого процесса с номером &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(0 \leq j &amp;lt; p):&amp;lt;/math&amp;gt;&lt;br /&gt;
## положим:&lt;br /&gt;
##: &amp;lt;math&amp;gt;pos = p-(k*(n-k)) \, \bmod \, p;&amp;lt;/math&amp;gt;&lt;br /&gt;
## на каждой итерации процессу необходимо вычислить &amp;lt;math&amp;gt;r_j&amp;lt;/math&amp;gt; значений целевой функции для соответствующих ему пар вида (медоид, не-медоид)   &amp;lt;math&amp;gt;(x_{m_s}, x_{o_h}), (x_{m_s}, x_{o_{h+1}}), ..., (x_{m_s}, x_{o_{n-k}}), (x_{m_{s+1}}, x_{o_0}), (x_{m_{s+1}}, x_{o_1}), . . . \, : &amp;lt;/math&amp;gt;&lt;br /&gt;
##:&amp;lt;math&amp;gt; r_j =   \begin{cases}&lt;br /&gt;
    \lfloor \frac{k*(n-k)}{p} \rfloor , 0 \leq j &amp;lt; pos &amp;amp; \quad\\&lt;br /&gt;
    \lceil \frac{k*(n-k)}{p} \rceil , pos  \leq j &amp;amp; \quad\\&lt;br /&gt;
  \end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
##: &amp;lt;math&amp;gt;s = \begin{cases}&lt;br /&gt;
    (r_j*j) \mbox{ div } (n-k) , 0 \leq j &amp;lt; pos &amp;amp; \quad\\&lt;br /&gt;
     ((r_j-1)*pos + r_j*(j-pos)) \mbox{ div } (n-k), pos  \leq j &amp;amp; \quad\\&lt;br /&gt;
  \end{cases}&amp;lt;/math&amp;gt; - порядковый номер &amp;lt;math&amp;gt;x_{m_s};&amp;lt;/math&amp;gt;&lt;br /&gt;
##: &amp;lt;math&amp;gt;h = \begin{cases}&lt;br /&gt;
    (r_j*j) \, \bmod \,  (n-k) , 0 \leq j &amp;lt; pos &amp;amp; \quad\\&lt;br /&gt;
     ((r_j-1)*pos + r_j*(j-pos)) \, \bmod \,  (n-k), pos  \leq j &amp;amp; \quad\\&lt;br /&gt;
  \end{cases}&amp;lt;/math&amp;gt; - порядковый номер &amp;lt;math&amp;gt;x_{o_h};&amp;lt;/math&amp;gt;&lt;br /&gt;
#:&lt;br /&gt;
#:&lt;br /&gt;
# каждому процессу с номером &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(0 \leq j &amp;lt; p):&amp;lt;/math&amp;gt;&lt;br /&gt;
## найти минимум среди вычисленных значений целевой функции для каждого из значений первого параметра &amp;lt;math&amp;gt;x_{m_s}&amp;lt;/math&amp;gt; по соответствующим ему &amp;lt;math&amp;gt;x_{o_h};&amp;lt;/math&amp;gt;&lt;br /&gt;
##* в данном случае может быть использована оптимизация, описанная в [[#Вычислительное ядро алгоритма|вычислительном ядре алгоритма]];&lt;br /&gt;
## переслать процессу с номером &amp;lt;math&amp;gt;N = s \, \bmod \, p&amp;lt;/math&amp;gt; (если &amp;lt;math&amp;gt;N \neq j&amp;lt;/math&amp;gt;) тройку &amp;lt;math&amp;gt;(F_{x_{m_s}, x_{o_h}}^{i_j}, x_{m_s}, x_{o_h})&amp;lt;/math&amp;gt; для всех обработанных &amp;lt;math&amp;gt;x_{m_s};&amp;lt;/math&amp;gt;&lt;br /&gt;
# для процессов с номерами &amp;lt;math&amp;gt;j&amp;lt;\min (p, k):&amp;lt;/math&amp;gt;&lt;br /&gt;
## принять описанные выше тройки от процессов, обработавших элементы &amp;lt;math&amp;gt;x_{m_{z \, \bmod \, p = j}}, z = \overline {0, k-1},&amp;lt;/math&amp;gt; в ответ на шаг 2.2;&lt;br /&gt;
## вычислить минимальное среди полученных значений целевой функции;&lt;br /&gt;
## запомнить &amp;lt;math&amp;gt;x_{m_s}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;x_{o_h}&amp;lt;/math&amp;gt;, на которых минимальное значение было достигнуто;&lt;br /&gt;
## при &amp;lt;math&amp;gt;j \neq 0 &amp;lt;/math&amp;gt; отправить тройку &amp;lt;math&amp;gt;(F_{x_{m_s}, x_{o_h}}^{i_j}, x_{m_s}, x_{o_h})&amp;lt;/math&amp;gt;, соответствующую выбранной паре, процессу с номером &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt;;&lt;br /&gt;
# для процесса с номером &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt;:&lt;br /&gt;
## принять тройки от процессов &amp;lt;math&amp;gt;(0, min(k-1, p-1)],&amp;lt;/math&amp;gt; в ответ на шаг 3.4;&lt;br /&gt;
## найти пару &amp;lt;math&amp;gt;(x_{m_s}, x_{o_h})&amp;lt;/math&amp;gt;, для которой целевая функция принимает минимальное значение;&lt;br /&gt;
## сравнить найденное минимальное значение с вычисленным значением целевой функции на предыдущей итерации фазы SWAP;&lt;br /&gt;
### (&#039;&#039; &#039;&#039;&#039;условие останова&#039;&#039;&#039; &#039;&#039;) если значение целевой функции не уменьшилось, остановить вычисление;&lt;br /&gt;
### иначе, разослать выявленную пару &amp;lt;math&amp;gt;(x_{m_s}, x_{o_h})&amp;lt;/math&amp;gt; при помощи широковещательной рассылки;&lt;br /&gt;
# для каждого процесса с номером &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(0 \leq j &amp;lt; p):&amp;lt;/math&amp;gt;&lt;br /&gt;
## принять пару &amp;lt;math&amp;gt;(x_{m_s}, x_{o_h})&amp;lt;/math&amp;gt; в ответ на шаг 4.3.2;&lt;br /&gt;
## скорректировать локальные копии множеств &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt;, заменяя элемент &amp;lt;math&amp;gt;x_{m_s}&amp;lt;/math&amp;gt; на элемент &amp;lt;math&amp;gt;x_{o_h}&amp;lt;/math&amp;gt; и наоборот;&lt;br /&gt;
## перейти к шагу 2.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Ограничения и недостатки =====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ограничения&#039;&#039;:&lt;br /&gt;
* предполагается, что матрица расстояний &amp;lt;math&amp;gt;D^{n * n}&amp;lt;/math&amp;gt; полностью помещается в памяти каждого процесса.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Недостатки&#039;&#039;:&lt;br /&gt;
* при распределении обсчитываемых целевых функций, каждому из процессов ставится в соответствие некоторая совокупность пар &amp;lt;math&amp;gt;(x_{m_s}, x_{o_h})&amp;lt;/math&amp;gt;, для которых нужно рассчитать значения целевой функции. В случае, если количество процессов не кратно количеству обрабатываемых кластеров, различные процессы получат пары у которых совпадают &amp;lt;math&amp;gt;x_{m_s}&amp;lt;/math&amp;gt;, что приведёт к совершению одинаковых вычислений на различных процессах: &amp;lt;math&amp;gt;   \min_{ x_{m_l} \in M_{i-1} \backslash \{x_{m_s}\} } ( \rho ( x_{m_l},x_j )), 1 \leq j \leq n;&amp;lt;/math&amp;gt;&lt;br /&gt;
* вычисление фазы SWAP успешно распараллеливается между &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; процессами, однако после этого происходит агрегация данных в 2 этапа относительно &amp;lt;math&amp;gt;(x_{m_s}, x_{o_h})&amp;lt;/math&amp;gt; для вычисления глобального минимума. На первом этапе данные собираются на первых &amp;lt;math&amp;gt;\min (p,k)&amp;lt;/math&amp;gt; процессах, где происходят локальные вычисления минимумов среди принятых данных (для каждого &amp;lt;math&amp;gt;x_{m_s}&amp;lt;/math&amp;gt;), после чего полученные минимумы и связанная с ними информация агрегируются на мастер-процессе, который вычисляет глобальный минимум и извещает о нём все остальные процессы. &amp;lt;br&amp;gt;Во время описанных вычислений все незадействованные процессы простаивают.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Дополнительные возможности&#039;&#039;:&lt;br /&gt;
* помимо описанной схемы, также есть возможность распараллелить операцию вычисления матрицы расстояний &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, однако это является отдельной алгоритмической задачей и не даёт существенного прироста производительности алгоритма.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Существующие параллельные реализации алгоритма PAM ====&lt;br /&gt;
&lt;br /&gt;
Примером другой параллельной реализации алгоритма PAM может служить реализация в пакете SPRINT для языка R (подробнее см. [[#Существующие реализации алгоритма|существующие реализации алгоритма]]).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
&lt;br /&gt;
Структура графа алгоритма (см. 1.7 [[#Информационный граф| Информационный граф алгоритма]]) такова, что позволяет надеяться на получение хорошей масштабируемости.&lt;br /&gt;
&lt;br /&gt;
Исследование масштабируемости параллельной реализации алгоритма Partitioning Around Medoids проводилось на суперкомпьютере BlueGene/P &amp;lt;ref&amp;gt;IBM BlueGene/P  - [http://hpc.cmc.msu.ru http://hpc.cmc.msu.ru]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
Отметим, что для данному суперкомпьютеру свойственна стабильность по времени вычисления одной и той же задачи при различных запусках.&lt;br /&gt;
Во время вычислений каждому MPI процессу соответствовало 1 ядро процессора PowerPC 450, 850 MHz с пиковой производительностью 3.4 GFlop/sec per core.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Набор и границы значений изменяемых [[Глоссарий#Параметры запуска|параметров запуска]] реализации алгоритма:&lt;br /&gt;
* число процессов (p):&lt;br /&gt;
** [1; 4 : 512] с шагом 4 процесса;&lt;br /&gt;
* размер кластеризуемого множества (n):&lt;br /&gt;
** [4; 16; 32; 64];&lt;br /&gt;
** [128 : 3200] с шагом 128 элементов;&lt;br /&gt;
* каждому размеру кластеризуемого множества соответствует количество кластеров для разбиения (k):&lt;br /&gt;
** [2; 4; 4; 8];&lt;br /&gt;
** [2 : 50] с шагом 2.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Особенности проведения эксперимента:&lt;br /&gt;
* тестовые данные являются псевдослучайными;&lt;br /&gt;
* для всех экспериментов использовался одинаковый набор данных;&lt;br /&gt;
* в соответствии с описанными параметрами запуска, для множеств размерности [128 : 3200], количество кластеров (k) прямо пропорционально размеру задачи (n).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В результате проведённых экспериментов был получен широкий диапазон [[Глоссарий#Эффективность распараллеливания|эффективности реализации]] алгоритма:&lt;br /&gt;
* минимальная эффективность реализации: &amp;lt;math&amp;gt;3.4 * 10^{-9} \, %&amp;lt;/math&amp;gt; достигается при использовании 512 процессов для множества из 4 элементов и 2-х кластеров (результат вызван избыточностью количества процессов по отношению к размеру задачи);&lt;br /&gt;
* максимальная эффективность реализации: &amp;lt;math&amp;gt;4.1 * 10^{-4} \, %&amp;lt;/math&amp;gt; достигается при использовании 4 процессов для множества из 128 элементов и 2 кластеров.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Абсолютная величина [[Глоссарий#Производительность|производительности алгоритма]] (GFlops) определялась как количество операций с плавающей точкой за секунду. Точное количество операций было вычислено на основании [[#Последовательная сложность алгоритма| последовательной сложности алгоритма]], целочисленные операции и операции работы с памятью не учитывались.&lt;br /&gt;
&lt;br /&gt;
Таким образом, производительность обусловлена как самим алгоритмом (его внутренняя структура определяет соотношение между операциями работы с памятью, операциями над целочисленными значениями и значениями с плавающей точкой), так и используемой реализацией.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
На следующих рисунках приведены графики производительности и эффективности выбранной реализации PAM в зависимости от изменяемых параметров запуска:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{|style=&amp;quot;margin: 0 auto;&amp;quot;&lt;br /&gt;
 | [[file:PAM-gflops.png|thumb|none|600px|Рисунок 5а. Параллельная реализация алгоритма PAM. Изменение производительности в зависимости от числа процессов и размера множества.]]&lt;br /&gt;
 | [[file:PAM-gflops-top-view.png|thumb|none|600px|Рисунок 5б. Параллельная реализация алгоритма PAM. Изменение производительности в зависимости от числа процессов и размера множества. Вид сверху.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
[[file:PAM-gflops.png|thumb|center|800px|Рисунок 5а. Параллельная реализация алгоритма PAM. Изменение производительности в зависимости от числа процессов и размера множества.]]&lt;br /&gt;
[[file:PAM-gflops-top-view.png|thumb|center|800px|Рисунок 5б. Параллельная реализация алгоритма PAM. Изменение производительности в зависимости от числа процессов и размера множества. Вид сверху.]]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
[[file:PAM-efficiency.png|thumb|center|800px|Рисунок 6. Параллельная реализация алгоритма PAM. Изменение эффективности в зависимости от числа процессов и размера множества.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
На рисунке 5б, видно, что пики организованы в прямые. Это обусловлено инвариантностью величины &amp;lt;math&amp;gt;a&amp;lt;/math&amp;gt; в соответствии с описанной в [[#Вычислительное ядро алгоритма | вычислительном ядре фазы SWAP]] оптимизацией. На рисунке 3 для [[#Информационный граф фазы SWAP| информационного графа фазы SWAP]] наглядно видно, что при построчном распределении вычислений &amp;lt;math&amp;gt;\overline{b}_{x_{m_s, o_h}}&amp;lt;/math&amp;gt; возможно возникновение следующих ситуаций (далее при &#039;&#039; &#039;&#039;&#039;k * (n-k) mod p == 0&#039;&#039;&#039; &#039;&#039; обозначим &#039;&#039; &#039;&#039;&#039;r = k * (n-k) / p&#039;&#039;&#039; &#039;&#039;):&lt;br /&gt;
# при &#039;&#039; &#039;&#039;&#039;r &amp;lt; (n-k)&#039;&#039;&#039; &#039;&#039;, если &#039;&#039; &#039;&#039;&#039;(n-k) mod r == 0&#039;&#039;&#039; &#039;&#039;, то каждому процессу необходимо вычислить ровно одну величину &amp;lt;math&amp;gt;\overline{a}_{x_{m_s}};&amp;lt;/math&amp;gt;&lt;br /&gt;
# при &#039;&#039; &#039;&#039;&#039;r &amp;amp;ge; (n-k)&#039;&#039;&#039; &#039;&#039;, если &#039;&#039; &#039;&#039;&#039;k mod p == 0&#039;&#039;&#039; &#039;&#039;, то каждому процессу необходимо вычислить несколько соответствующих ему величин &amp;lt;math&amp;gt;\overline{a}_{x_{m_s}},&amp;lt;/math&amp;gt; при этом каждая величина будет вычислена ровно в одном процессе;&lt;br /&gt;
# в остальных случаях вычисления величин &amp;lt;math&amp;gt;\overline{b}_{x_{m_s, o_h}}&amp;lt;/math&amp;gt; распределяются между процессами таким образом, что часть процессов обрабатывает больше величин &amp;lt;math&amp;gt;\overline{a}_{x_{m_s}}&amp;lt;/math&amp;gt; нежели остальные (ситуация возникает при обработке процессом последних элементов одной строки и первых элементов следующей). Подобная ситуация приводит к дополнительным вычислениям на некоторых процессах и, как следствие, к простою остальных, в связи с чем происходит падение производительности.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Первые два случая приводят к равномерному распределению нагрузки между процессами, и им соответствуют видимые пики на приведённых рисунках 5a, 5б, 6. Для 3-го случая из-за неравномерной загрузки процессов достигаемая производительность падает.&lt;br /&gt;
&lt;br /&gt;
Второй случай соответствует размеру задачи меньшему, чем количество процессов и на практике маловероятен.&lt;br /&gt;
Таким образом, для повышения производительности следует выбирать количество процессов так, чтобы &#039;&#039; &#039;&#039;&#039;k * (n-k)&#039;&#039;&#039; &#039;&#039; и &#039;&#039; &#039;&#039;&#039;(n-k)&#039;&#039;&#039; &#039;&#039; были кратны &#039;&#039; &#039;&#039;&#039;p&#039;&#039;&#039; &#039;&#039; и &#039;&#039; &#039;&#039;&#039;k * (n-k) div p&#039;&#039;&#039; &#039;&#039; соответственно.&lt;br /&gt;
&lt;br /&gt;
Для исследуемой реализации, вычисление величин &amp;lt;math&amp;gt;\overline{a}_{x_{m_s}}&amp;lt;/math&amp;gt; может быть оптимизировано (за счёт распределения между процессами и последующих пересылок). Однако принципиальный вид графиков останется тем же: пики будут наблюдаться для случаев равномерного распределения вычислительных задач между процессами.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Построим оценки масштабируемости выбранной реализации алгоритма PAM:&lt;br /&gt;
* По числу процессов: &amp;lt;math&amp;gt;- \, 1.6 * 10^{-8}.&amp;lt;/math&amp;gt; С ростом числа процессов эффективность на рассмотренной области изменений параметров запуска уменьшается. Этот результат вызван ростом времени, затрачиваемого на пересылку данных, то есть ростом накладных расходов на организацию параллельного выполнения.&lt;br /&gt;
* По размеру задачи: &amp;lt;math&amp;gt;3.9 * 10^{-7}&amp;lt;/math&amp;gt;. С ростом размера задачи эффективность на рассмотренной области изменений параметров запуска увеличивается. Этот результат вызван увеличением количества вычислений относительно объема пересылок данных.&lt;br /&gt;
* Общая оценка масштабируемости: &amp;lt;math&amp;gt;- \, 1.2 * 10^{-9}&amp;lt;/math&amp;gt;. При рассмотрении области параметров запуска в целом можно говорить о том, что с ростом размера задачи и числа процессов эффективность незначительно падает.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[https://github.com/phonexicum/pam-mpi-cmc Исследованная параллельная реализация на языке C++] (реализация написана самостоятельно)&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
# Последовательная реализация алгоритма PAM в пакете ClusterR на языке R:&lt;br /&gt;
#* Лицензия: MIT&lt;br /&gt;
#* [https://cran.r-project.org/package=ClusterR веб-страница фреймворка (исходный код, системные требования и справочное руководство)]&lt;br /&gt;
#* Алгоритм PAM реализован в функции &#039;Cluster_Medoids&#039;. Отличительная особенность реализации &amp;lt;ref&amp;gt;Lampros Mouselimis [https://cran.r-project.org/web/packages/cluster/cluster.pdf Package &#039;ClusterR&#039;]. October 8, 2016&amp;lt;/ref&amp;gt;:&lt;br /&gt;
#** для задания метрики между элементами кластеризуемого множества передаётся строка, задающая одну из реализованных в алгоритме метрик. Данный подход теряет одно из преимуществ алгоритма PAM, позволяющее в качестве матрицы расстояний использовать произвольную матрицу различий.&lt;br /&gt;
#:&lt;br /&gt;
#:&lt;br /&gt;
# Последовательная реализация алгоритма PAM в пакете Cluster на языке R:&lt;br /&gt;
#* Лицензия: GPL (≥2)&lt;br /&gt;
#* [https://cran.r-project.org/package=cluster веб-страница фреймворка (исходный код, системные требования и справочное руководство)]&lt;br /&gt;
#* Алгоритм PAM реализован в функции &#039;pam()&#039;. Данная реализация имеет следующие особенности &amp;lt;ref&amp;gt;Martin Maechler., etc. [https://cran.r-project.org/web/packages/cluster/cluster.pdf Package &#039;cluster&#039;]. October 8, 2016&amp;lt;/ref&amp;gt;:&lt;br /&gt;
#** функция может принимать на вход не множество точек, а матрицу расстояний между ними;&lt;br /&gt;
#** реализация более гибкая, так как принимает на вход матрицу различий элементов, а не использует какую-либо метрику;&lt;br /&gt;
#** может быть предоставлено графическое отображение.&lt;br /&gt;
#:&lt;br /&gt;
#:&lt;br /&gt;
#:&lt;br /&gt;
# Параллельная реализация алгоритма PAM в пакете SPRINT (Simple Parallel R INTerface - параллельный фреймворк) на языке R:&lt;br /&gt;
#* Лицензия: GPL (≥3)&lt;br /&gt;
#* [https://cran.r-project.org/package=sprint веб-страница фреймворка (исходный код, системные требования и справочное руководство)]&lt;br /&gt;
#* Алгоритм PAM реализован в фукции &#039;ppam()&#039;. Входные параметры данной функции схожи с параметрами, задаваемыми в линейной реализации &#039;pam()&#039; пакета Cluster языка R. Отличительной особенностью является подача на вход предвычисленной матрицы расстояний (например, с помощью функции &#039;pcor()&#039; из этой же библиотеки).&amp;lt;ref&amp;gt;University of Edinburgh SPRINT Team. [https://cran.r-project.org/web/packages/sprint/sprint.pdf Package &#039;sprint&#039;]. February 20, 2015&amp;lt;/ref&amp;gt;&lt;br /&gt;
#:&lt;br /&gt;
#:&lt;br /&gt;
# Параллельная реализация алгоритма PAM на основе операций MapReduce на Hadoop кластере.&lt;br /&gt;
#* В рамках исследования по ускорению анализа информации о геноме были созданы реализации алгоритма PAM с использованием технологии MPI и технологии MapReduce. Реализация в открытом досупе отсутствует. &amp;lt;ref&amp;gt;Dobrzelecki B. et al. Managing and analysing Genomic Data using HPC and Clouds //Grid and Cloud Database Management. – Springer Berlin Heidelberg, 2011. – С. 261-277.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
MKL, ScaLAPACK, PETSc, FFTW, ATLAS, Magma и другие подобные библиотеки.&lt;br /&gt;
&lt;br /&gt;
* Дать ссылки на существующие последовательные и параллельные реализации алгоритма (&amp;quot;уже доступные&amp;quot;)&lt;br /&gt;
* Реализация - коммерческая/свободная, лицензия&lt;br /&gt;
* ссылка на дистрибутив и описание&lt;br /&gt;
* особенности, достоинства/недостатки, ....&lt;br /&gt;
&lt;br /&gt;
гугл-запрос: &amp;quot;partitioning around medoids&amp;quot; &amp;quot;PAM&amp;quot; BUILD SWAP &amp;quot;MPI&amp;quot; &amp;quot;program&amp;quot; &amp;quot;package&amp;quot; -worldwidescience&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;/div&gt;</summary>
		<author><name>Dexter</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:Avasilenko/Partitioning_Around_Medoids_(PAM)&amp;diff=19069</id>
		<title>Участник:Avasilenko/Partitioning Around Medoids (PAM)</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:Avasilenko/Partitioning_Around_Medoids_(PAM)&amp;diff=19069"/>
		<updated>2016-11-24T08:27:03Z</updated>

		<summary type="html">&lt;p&gt;Dexter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{Assignment|Преподаватель 1|Dexter}}&lt;br /&gt;
{{Assignment|Zhum}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Partitioning Around Medoids&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(T*kn^2)&amp;lt;/math&amp;gt;&lt;br /&gt;
| input_data        = &amp;lt;math&amp;gt;n*(n-1)+2&amp;lt;/math&amp;gt;&lt;br /&gt;
| output_data       = &amp;lt;math&amp;gt;k+1&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_height         = &amp;lt;math&amp;gt;O(T*kn)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(k(n-k))&amp;lt;/math&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Авторы&#039;&#039;&#039;:&lt;br /&gt;
* [[Участник:Avasilenko|А.Э.Василенко]] (отвечает за программистскую составляющую);&lt;br /&gt;
* [[Участник:Anastasia|А.В.Тузикова]] (отвечает за математическую составляющую).&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;Rousseeuw P. J., Kaufman L. Finding Groups in Data. – Wiley Online Library, 1990.&amp;lt;/ref&amp;gt;. Более того - это важная часть процесса познания мира, в котором мы живем. Мы учим детей различать кошек и собак, воду и песок, мужчин и женщин путем постоянного развития и улучшения подсознательных схем классификации. Примеры есть и во взрослой жизни – в химии необходимо классифицировать соединения, в археологии – объединять находки по периодам и т.д.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Задача кластеризации&#039;&#039;&#039; - разделение множества объектов на заданное число множеств с минимизацией некоторого функционала - является популярной задачей, относится к разделу машинного обучения и находит применение в таких областях, как анализ текста, биоинформатика, интеллектуальные транспортные системы и др. &amp;lt;ref&amp;gt; Речкалов Т.В. Параллельный алгоритм кластеризации для многоядерного сопроцессора Intel Xeon Phi // Суперкомпьютерные дни в России: Труды vеждународной конференции. – М.: Изд-во МГУ, 2015, c. 532.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Существует несколько видов кластеризации&amp;lt;ref&amp;gt;Маннинг К.Д., Введение в информационный поиск: пер. с англ. / К.Д. Маннинг, П. Рагхаван, Х.Шютце - М. : Вильямс, 2011. - 528.&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;плоская кластеризация&#039;&#039; (&#039;&#039;flat clustering&#039;&#039;) - порождает совокупность кластеров, не имеющих явных взаимосвязей;&lt;br /&gt;
* &#039;&#039;иерархическая кластеризация&#039;&#039; (&#039;&#039;hierarchical clustering&#039;&#039;) - создаёт иерархию кластеров.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;PAM&#039;&#039;&#039; (&#039;&#039;&#039;Partitioning Around Medoids&#039;&#039;&#039;) - плоский алгоритм кластеризации, позволяющий выделить &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;
Модель &amp;lt;ref&amp;gt;Kaufman, L. and Rousseeuw, P.J., Clustering by means of Medoids. In: Y. Dodge and North-Holland, editor. Statistical Data Analysis Based on the L1-Norm and Related Methods. Springer US; 1987, p. 405–416.&amp;lt;/ref&amp;gt;, лежащая в основе алгоритма PAM, основана на выборе &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; объектов, являющихся характерными точками соответствующего кластера. Таким образом, кластерам сопоставляются принадлежащие им объекты, называемые &#039;&#039;&#039;медоидами&#039;&#039;&#039;, на основании которых распределяются остальные объекты по принципу наибольшего сходства. Cама модель называется моделью &#039;&#039;&#039;k-medoids&#039;&#039;&#039; (не путать с моделью &#039;&#039;k-median&#039;&#039;).&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
PAM состоит из двух фаз: &#039;&#039;&#039;BUILD&#039;&#039;&#039; и &#039;&#039;&#039;SWAP&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
*   на фазе BUILD выполняется первичная кластеризация, в ходе которой последовательно выбираются &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; объектов в качестве медоидов;&lt;br /&gt;
*   фаза SWAP представляет собой итерационный процесс, в ходе которого производятся попытки улучшить множество медоидов. Алгоритм выполняет поиск пары объектов (медоид, не-медоид), минимизирующих целевую функцию при замене, после чего обновляет множество медоидов.&lt;br /&gt;
&lt;br /&gt;
На каждой итерации алгоритма выбирается пара (медоид, не-медоид) такая, что замена медоида &amp;lt;math&amp;gt;x_{m_l}&amp;lt;/math&amp;gt; на не-медоид &amp;lt;math&amp;gt;x_{o_h}&amp;lt;/math&amp;gt; дает лучшую кластеризацию из возможных. Оценка кластеризации выполняется с помощью целевой функции, вычисляемой как сумма расстояний от каждого объекта до ближайшего медоида:&lt;br /&gt;
 &lt;br /&gt;
:&amp;lt;math&amp;gt;E = \sum_{j = 1}^n \min_{1 \leq l \leq k} \rho ( x_{m_l},x_{o_j} )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Процедура изменения множества медоидов повторяется, пока есть возможность улучшения значения целевой функции.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
 &lt;br /&gt;
&#039;&#039;Исходные данные&#039;&#039;:&lt;br /&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;x_i&amp;lt;/math&amp;gt; - кортеж, состоящий из &amp;lt;math&amp;gt; w &amp;lt;/math&amp;gt; вещественных чисел;&lt;br /&gt;
*   симметрическая матрица &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, элементы матрицы &amp;lt;math&amp;gt;d_{ij}=d(i,j)&amp;lt;/math&amp;gt; - вычисленные расстояния между объектами &amp;lt;math&amp;gt;x_i, x_j&amp;lt;/math&amp;gt;;&lt;br /&gt;
*   количество кластеров &amp;lt;math&amp;gt;k \leq n.&amp;lt;/math&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
&#039;&#039;Обозначения&#039;&#039;:&lt;br /&gt;
*   &amp;lt;math&amp;gt;M = \{ x_{m_1}, x_{m_2}, ... , x_{m_k} \} &amp;lt;/math&amp;gt; - множество медоидов, &amp;lt;math&amp;gt; M \subseteq X ;&amp;lt;/math&amp;gt;&lt;br /&gt;
*   &amp;lt;math&amp;gt;O = \{ x_{o_1}, x_{o_2}, ... , x_{o_r} \} &amp;lt;/math&amp;gt; - множество не-медоидов, &amp;lt;math&amp;gt; O \subseteq X, &amp;lt;/math&amp;gt; где &amp;lt;math&amp;gt;r=n-k;&amp;lt;/math&amp;gt;&lt;br /&gt;
*   &amp;lt;math&amp;gt;d_{ij}=\rho (x_i, x_j )&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt; \rho  : X \times X \rightarrow R &amp;lt;/math&amp;gt; — метрика расстояния;&lt;br /&gt;
*   &amp;lt;math&amp;gt;F_{M,O} = \sum_{j = 1}^{n} \min_{ x_{m_l} \in M} \rho ( x_{m_l},x_{o_j} )&amp;lt;/math&amp;gt; - значение целевой функции для заданных множеств &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;O;&amp;lt;/math&amp;gt;&lt;br /&gt;
*   &amp;lt;math&amp;gt;T^i&amp;lt;/math&amp;gt; - изменение целевой функции на &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-м шаге фазы SWAP.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Выходные данные&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;M = \{ x_{m_1}, x_{m_2}, ... , x_{m_k} \}&amp;lt;/math&amp;gt; - множество медоидов;&lt;br /&gt;
* &amp;lt;math&amp;gt;K_{m_i} = \{ x_{o_h} \in O \| x_{m_i} = \arg \min_{x_{m_s} \in M} \rho (x_{o_h}, x_{m_s}) \}, 1 \leq i \leq k&amp;lt;/math&amp;gt; - искомые кластеры.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Вычислительные формулы метода&#039;&#039;:&lt;br /&gt;
 &lt;br /&gt;
*   &#039;&#039;фаза BUILD&#039;&#039; (состоит из &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; шагов последовательного выбора &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; медоидов):&lt;br /&gt;
**   &amp;lt;math&amp;gt;O_0 = X, M_0 = \varnothing ;&amp;lt;/math&amp;gt;&lt;br /&gt;
**   &amp;lt;math&amp;gt;x_{m_1} = \arg \min_{x_{o_h} \in O_0} \sum_{j = 1}^n \rho \left ( x_{o_h},x_j \right ), O_1 = O_0 \backslash \{x_{m_1}\}, M_1 = M_1 \cup \{x_{m_1}\} ; &amp;lt;/math&amp;gt;&lt;br /&gt;
**   &amp;lt;math&amp;gt;x_{m_2} = \arg \min_{x_{o_h} \in O_1} \sum_{j = 1}^{n} \min ( \rho ( x_{m_1},x_j ), \rho ( x_{o_h},x_j ) ), O_2 = O_1 \backslash \{x_{m_2}\}, M_2 = M_1 \cup \{x_{m_2}\} ; &amp;lt;/math&amp;gt;&lt;br /&gt;
**   &amp;lt;math&amp;gt;x_{m_3} = \arg \min_{x_{o_h} \in O_2} \sum_{j = 1}^{n} \min_{1 \leq l \leq 2} ( \rho ( x_{m_l},x_j ) , \rho ( x_{o_h},x_j ) ) , O_3 = O_2 \backslash \{x_{m_3}\}, M_3 = M_3 \cup \{x_{m_3}\} ; &amp;lt;/math&amp;gt;&lt;br /&gt;
** ...&lt;br /&gt;
**   &amp;lt;math&amp;gt;x_{m_k} = \arg \min_{x_{o_h} \in O_{k-1}} \sum_{j = 1}^{n} \min_{ x_{m_l} \in M_{k-1}} ( \rho ( x_{m_l},x_j ), \rho ( x_{o_h},x_j ) ) , O_k = O_{k-1} \backslash \{x_{m_k}\}, M_k = M_{k-1} \cup \{x_{m_k}\} ; &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;фаза SWAP&#039;&#039; (итерационный процесс):&lt;br /&gt;
** начальное приближение: &amp;lt;math&amp;gt;O_0 = O_k^{BUILD}, M_0 = M_k^{BUILD};&amp;lt;/math&amp;gt;&lt;br /&gt;
** &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-й шаг итерации:&lt;br /&gt;
*** вычисление целевой функции при оптимальной замене (замене, при которой достигается лучшая кластеризация из возможных на текущей итерации): &amp;lt;br&amp;gt;&amp;lt;math&amp;gt;F^i = \min_{x_{m_s} \in M_{i-1} , x_{o_h} \in O_{i-1}} \sum_{j = 1}^{n} \min_{ x_{m_l} \in M_{i-1} \backslash \{x_{m_s}\} } ( \rho ( x_{m_l},x_j ), \rho ( x_{o_h},x_j) ); &amp;lt;/math&amp;gt;&lt;br /&gt;
*** определение пары (медоид, не-медоид), на которой достигается оптимальная замена: &amp;lt;br&amp;gt;&amp;lt;math&amp;gt; (x_{m_s}, x_{o_h}) = \arg F^i; &amp;lt;/math&amp;gt;&lt;br /&gt;
*** проверка критерия останова;&lt;br /&gt;
*** изменение множеств в соответствии с выбранной парой &amp;lt;math&amp;gt; (x_{m_s}, x_{o_h}):&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&amp;lt;math&amp;gt;M_i = M_{i-1} \backslash \{x_{m_s}\} \cup \{x_{o_h}\} , O_i = O_{i-1} \cup \{x_{m_s}\} \backslash \{x_{o_h}\} ;&amp;lt;/math&amp;gt;&lt;br /&gt;
** критерий останова:&lt;br /&gt;
*** &amp;lt;math&amp;gt;T^i = F^{i-1} - F^{i} \leq 0 .&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вычислительное ядро алгоритма PAM на этапе BUILD&#039;&#039;&#039; состоит из многочисленных вычислений значений целевой функции при различных вариантах выбора дополнительного медоида (шаг алгоритма &amp;lt;math&amp;gt;1 \leq i \leq k&amp;lt;/math&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;F^i = \min_{x_{o_h} \in O_{i-1}} \sum_{j = 1}^{n} \min_{ x_{m_l} \in M_{i-1}} ( \rho ( x_{m_l},x_j ), \rho ( x_{o_h},x_j ) ) = \min_{x_{o_h} \in O_{i-1}} \sum_{j = 1}^{n} \overline{MIN}_{i, x_{o_h}}^{(j)},&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где:&lt;br /&gt;
* &amp;lt;math&amp;gt;\overline{MIN}_{1, x_{o_h} \in O_0} = \{ \rho (x_{o_h}, x_j ) \| 1 \leq j \leq n \};&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;\overline{MIN}_{i, x_{o_h} \in O_{i-1}} = \{ \min ( \overline{MIN}_{i-1, x_{m_{i-1}}}^{(j)}, \rho (x_{o_h}, x_j) ) \| 1 \leq j \leq n \}, \forall i: 1 &amp;lt; i \leq k.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С каждой итерацией количество вариантов выбора дополнительных медоидов уменьшается на единицу, таким образом, на &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-м шаге целевую функцию нужно вычислить лишь &amp;lt;math&amp;gt;|O_{i-1}| = n-i+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;
* таким образом, на каждой последующей итерации можно использовать величину, вычисленную на предыдущем шаге, что позволяет сократить число вычислений минимумов.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Вычислительное ядро алгоритма PAM на этапе SWAP&#039;&#039;&#039; состоит из многочисленных вычислений значений целевой функции при различных вариантах замены некоторого существующего медоида на элемент из числа не-медоидов. &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-я итерация фазы SWAP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;F^i = \min_{x_{m_s} \in M_{i-1} , x_{o_h} \in O_{i-1}} \sum_{j = 1}^{n} \min_{ x_{m_l} \in M_{i-1} \backslash \{x_{m_s}\} } ( \rho ( x_{m_l},x_j ), \rho ( x_{o_h},x_j) ) =&amp;lt;/math&amp;gt;&amp;lt;br&amp;gt;&amp;lt;math&amp;gt;= \min_{x_{m_s} \in M_{i-1} } \min_{x_{o_h} \in O_{i-1}} \sum_{j = 1}^{n} \min ( \min_{ x_{m_l} \in M_{i-1} \backslash \{x_{m_s}\} } ( \rho ( x_{m_l},x_j )) , \rho ( x_{o_h},x_j) )&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;x_{o_h}&amp;lt;/math&amp;gt;, для которых вычисляется &amp;lt;math&amp;gt;\sum_{j = 1}^{n} \min (a, b)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;a&amp;lt;/math&amp;gt; есть &amp;lt;math&amp;gt; \min_{ x_{m_l} \in M_{i-1} \backslash \{x_{m_s}\} } ( \rho ( x_{m_l},x_j )),&amp;lt;/math&amp;gt; и является инвариантом по отношению к &amp;lt;math&amp;gt;\min_{x_{o_h} \in O_{i-1}} \sum_{j = 1}^{n} \min ( \min_{ x_{m_l} \in M_{i-1} \backslash \{x_{m_s}\} } ( \rho ( x_{m_l},x_j )) , \rho ( x_{o_h},x_j) ),&amp;lt;/math&amp;gt; что позволяет предвычислить элемент &amp;lt;math&amp;gt;a.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Опишем макрооперации алгоритма&#039;&#039;:&lt;br /&gt;
* в случае если алгоритму PAM на вход подаётся набор точек с их координатами в пространстве &amp;lt;math&amp;gt;R^w,&amp;lt;/math&amp;gt; то необходимо вычислить матрицу расстояний. Для этого может быть использована, например, евклидова метрика:&lt;br /&gt;
*: &amp;lt;math&amp;gt;\rho (p,q)=\sqrt{(p_1-q_1)^2+(p_2-q_2)^2+\dots+(p_w-q_w)^2} = \sqrt{\sum_{j=1}^w (p_j-q_j)^2} &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;p, q \in R^w;&amp;lt;/math&amp;gt;&lt;br /&gt;
* нахождение минимального среди значений, принимаемых некоторой функцией &amp;lt;math&amp;gt;value,&amp;lt;/math&amp;gt; определённой на дискретном множестве &amp;lt;math&amp;gt;Y=\{y_i\}, \, i = \overline{(1,r)}:&amp;lt;/math&amp;gt;&lt;br /&gt;
*: &amp;lt;math&amp;gt;minimum_{y \in Y } (value (y)) = \min \Bigg(value(y_1), \min \bigg(value(y_2), \min \Big(\dots , \min(value(y_{r-1}), value(y_{r})) ... \Big) \bigg)\Bigg);&amp;lt;/math&amp;gt;&lt;br /&gt;
* вычисление вектора инвариантов, используемых при оптимизации фазы SWAP (см. вычислительное ядро алгоритма):&lt;br /&gt;
*: &amp;lt;math&amp;gt;\overline{a} = \{ minimum_{ x_{m_l} \in M_{i-1} \backslash \{x_{m_s}\} } ( \rho ( x_{m_l}, x_j ) ) \| 1 \leq j \leq n \},&amp;lt;/math&amp;gt; где &amp;lt;math&amp;gt;i - &amp;lt;/math&amp;gt;номер итерации;&lt;br /&gt;
* вычисление вектора расстояний от каждой точки заданного множества &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt; до ближайшего медоида из множества &amp;lt;math&amp;gt;M_{i-1} \backslash \{x_{m_s}\},&amp;lt;/math&amp;gt; где &amp;lt;math&amp;gt;i - &amp;lt;/math&amp;gt;номер итерации фазы SWAP: &lt;br /&gt;
*: &amp;lt;math&amp;gt;\overline{b} = \{ \min (\overline{a}^{(j)}, \rho ( x_{o_p}, x_j )) \| 1 \leq j \leq n \};&amp;lt;/math&amp;gt;&lt;br /&gt;
* сложение компонент вектора: &amp;lt;math&amp;gt;S = \sum_{j = 1}^{n} \overline{f}^{(j)}.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Макроструктура вычислительного ядра алгоритма PAM&#039;&#039; может быть выражена через макрооперации следующим образом:&lt;br /&gt;
* для ядра фазы BUILD:&lt;br /&gt;
*::: &amp;lt;math&amp;gt;F^i = minimum_{ x_{o_h} \in O_{i-1} } ( S \, ( \overline{f} (x_{o_h}) )),&amp;lt;/math&amp;gt;&lt;br /&gt;
*::: &amp;lt;math&amp;gt;\overline{f} = \{ \min \,( \overline{MIN}_{i, x_{o_h}}^{(j)}, \rho (x_{o_h}, x_j)) \| 1 \leq j \leq n \}, &amp;lt;/math&amp;gt; где&lt;br /&gt;
*# &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; вычисляется &amp;lt;math&amp;gt;n-i+1&amp;lt;/math&amp;gt; раз;&lt;br /&gt;
*# &amp;lt;math&amp;gt;minimum&amp;lt;/math&amp;gt; находится &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; раз при вычислении наилучшего значения целевой функции на текущей итерации.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* для ядра фазы SWAP:&lt;br /&gt;
*::: &amp;lt;math&amp;gt;F^i = minimum_{ x_{m_s} \in M_{i-1} , x_{o_h} \in O_{i-1} } ( S \, ( \overline{b} \, ( x_{o_h}, \overline{a} \, (x_{m_s}) ) )),&amp;lt;/math&amp;gt; где:&lt;br /&gt;
*# &amp;lt;math&amp;gt;minimum&amp;lt;/math&amp;gt; находится &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; раз  в процессе вычисления макрооперации &amp;lt;math&amp;gt;\overline {a};&amp;lt;/math&amp;gt;&lt;br /&gt;
*# &amp;lt;math&amp;gt;\overline {a}&amp;lt;/math&amp;gt; вычисляется &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; раз и использует вычисленные на шаге 1 минимальные значения;&lt;br /&gt;
*# &amp;lt;math&amp;gt;\overline {b}&amp;lt;/math&amp;gt; вычисляется &amp;lt;math&amp;gt;k(n-k)&amp;lt;/math&amp;gt; раз и использует вычисленные на шаге 2 значения &amp;lt;math&amp;gt;\overline {a};&amp;lt;/math&amp;gt;&lt;br /&gt;
*# &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; вычисляется &amp;lt;math&amp;gt;k(n-k)&amp;lt;/math&amp;gt; раз и использует вычисленные на шаге 3 значения &amp;lt;math&amp;gt;\overline {b};&amp;lt;/math&amp;gt;&lt;br /&gt;
*# &amp;lt;math&amp;gt;minimum&amp;lt;/math&amp;gt; находится &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; раз при вычислении наилучшего значения целевой функции на текущей итерации.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Псевдокод алгоритма&#039;&#039;:&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;D&amp;lt;/math&amp;gt;, количество кластеров &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;&lt;br /&gt;
 &#039;&#039;&#039;Выход&#039;&#039;&#039; : Множество медоидов &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt;&lt;br /&gt;
 0  Если на вход было подано множество объектов, необходимо предварительно вычислить матрицу расстояний;&lt;br /&gt;
 1  Инициализация множеств &amp;lt;math&amp;gt;M := \varnothing, O := X;&amp;lt;/math&amp;gt;&lt;br /&gt;
 &amp;amp;nbsp;&lt;br /&gt;
    // фаза BUILD&lt;br /&gt;
 2  &#039;&#039;&#039;for (int i := 1; i &amp;lt;= k; i++)&#039;&#039;&#039; {&lt;br /&gt;
        // Найти &amp;lt;math&amp;gt;x_{m_i}:&amp;lt;/math&amp;gt;&lt;br /&gt;
        {&lt;br /&gt;
 3          Для всех &amp;lt;math&amp;gt;x_{o_h} \in O&amp;lt;/math&amp;gt; вычислить &amp;lt;math&amp;gt;F_{M \cup \{x_{o_h}\}, O \backslash \{x_{o_h}\}};&amp;lt;/math&amp;gt;&lt;br /&gt;
 4          Положить &amp;lt;math&amp;gt;x_{m_i}&amp;lt;/math&amp;gt; равным &amp;lt;math&amp;gt;x_{o_h}&amp;lt;/math&amp;gt;, соответствующему минимальному из вычисленных &amp;lt;math&amp;gt;F;&amp;lt;/math&amp;gt;&lt;br /&gt;
        }&lt;br /&gt;
 5      Обновить множества &amp;lt;math&amp;gt;M := M \cup \{x_{m_i}\}, O := O \backslash \{x_{m_i}\};&amp;lt;/math&amp;gt;&lt;br /&gt;
    }&lt;br /&gt;
    // фаза SWAP&lt;br /&gt;
 6  &#039;&#039;&#039;while (1)&#039;&#039;&#039; {&lt;br /&gt;
        // Найти пару &amp;lt;math&amp;gt;(x_{m_s}, x_{o_h}),&amp;lt;/math&amp;gt; на которой достигается оптимальная замена:&lt;br /&gt;
        {&lt;br /&gt;
 7          Для всех &amp;lt;math&amp;gt;x_{m_i} \in M, x_{o_j} \in O&amp;lt;/math&amp;gt; вычислить &amp;lt;math&amp;gt;F^i;&amp;lt;/math&amp;gt; // вычисление проводить с учётом приведённой ранее оптимизации (см. 1.3 [[#Вычислительное ядро алгоритма|Вычислительное ядро алгоритма]]);&lt;br /&gt;
 8          Положить пару &amp;lt;math&amp;gt;(x_{m_s}, x_{o_h})&amp;lt;/math&amp;gt; равной паре &amp;lt;math&amp;gt;(x_{m_i}, x_{o_j})&amp;lt;/math&amp;gt;, соответствующей минимальному из вычисленных &amp;lt;math&amp;gt;F;&amp;lt;/math&amp;gt;&lt;br /&gt;
        }&lt;br /&gt;
 9      Вычислить &amp;lt;math&amp;gt;T^i;&amp;lt;/math&amp;gt; // критерий останова (см. 1.2 [[#Математическое описание алгоритма|Математическое описание алгоритма]])&lt;br /&gt;
 10     &#039;&#039;&#039;if&#039;&#039;&#039; &amp;lt;math&amp;gt;(T^i &amp;gt; 0)&amp;lt;/math&amp;gt; {&lt;br /&gt;
 11         Обновить множества &amp;lt;math&amp;gt;M := M \backslash \{x_{m_s}\} \cup \{x_{o_h}\}, O := O \cup \{x_{m_s}\} \backslash \{x_{o_h}\};&amp;lt;/math&amp;gt;&lt;br /&gt;
 12     } &#039;&#039;&#039;else&#039;&#039;&#039; {&lt;br /&gt;
 13         &#039;&#039;&#039;break&#039;&#039;&#039;;&lt;br /&gt;
        }&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Оптимизации&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Предвычисление матрицы расстояний&#039;&#039;&#039;. Необходимо предварительно вычислить матрицу расстояний и сохранить её в памяти, так как в ходе вычисления алгоритма многократно используются расстояния между элементами, а вычисление каждого из них является ресурсоёмкой операцией из нескольких умножений и одного извлечения квадратного корня.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Минимизация кеш-промахов&#039;&#039;&#039;. Матрица расстояний, к которой постоянно выполняется доступ на чтение для вычисления минимумов и их суммирования, должна храниться в памяти как матрица размера &amp;lt;math&amp;gt;n*n&amp;lt;/math&amp;gt;, несмотря на то, что она симметрическая и достаточно хранить лишь половину (элементы над или под главной диагональю). Данная оптимизация потребует использования в 2 раза большего количества памяти для хранения расстояний (а это является главным расходом памяти программы, так как все остальные используемые данные являются временными (локальными для каждой операции) и представляют из себя несколько векторов длинной &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; элементов). Однако так как в данном алгоритме доступ к матрице осуществляется построчно (в  [[#Вычислительное ядро алгоритма|вычислительном ядре алгоритма]] поэлементно ищутся  минимумы 2-х векторов, после чего все они складываются), то в этом случае из матрицы можно будет читать данные по строкам подряд, что снижает количество кеш-промахов. Использование только половины матрицы приводит к частым промахам в кеше в связи с необходимостью загрузки части векторов по строкам, а части - по столбцам.&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;\frac{n*(n-1)}{2}&amp;lt;/math&amp;gt; операций вычисления расстояний;&lt;br /&gt;
* сложность каждой операции вычисления расстояния (для случая использования Евклидовой метрики) равна &amp;lt;math&amp;gt;2*w-1&amp;lt;/math&amp;gt; операций сложения и вычитания, &amp;lt;math&amp;gt;w&amp;lt;/math&amp;gt; операций возведения в квадрат (умножения) и &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; операции извлечения квадратного корня.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
На основании формулы из описания &#039;&#039;&#039;вычислительного ядра фазы BUILD&#039;&#039;&#039; определим сложность выполнения всего этапа.&lt;br /&gt;
&lt;br /&gt;
Обозначим:&lt;br /&gt;
*&amp;lt;math&amp;gt;summs&amp;lt;/math&amp;gt; - операция сложения двух вещественных чисел;&lt;br /&gt;
*&amp;lt;math&amp;gt;mins&amp;lt;/math&amp;gt; - операция нахождения минимума для двух вещественных чисел.&lt;br /&gt;
&lt;br /&gt;
Тогда, количество операций равно:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;S = ( ( (n-1) summs ) * (n-1+1) + (n-1+1-1)mins) + \sum_{i = 2}^{k} ( ( (1 mins)*(n-1) + (n-1) summs ) * (n-i+1) + (n-i+1-1)mins) \Rightarrow&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\Rightarrow S =&lt;br /&gt;
  \begin{cases}&lt;br /&gt;
    S(mins) = ( ( 0 ) * (n-1+1) + (n-1+1-1)mins) + \sum_{i = 2}^{k} ( ( (1 mins)*(n-1)) * (n-i+1) + (n-i+1-1)mins ) &amp;amp; \quad\\&lt;br /&gt;
    S(summs) = \sum_{i = 1}^{k} ( ( (n-1) summs ) * (n-i+1) ) &amp;amp; \quad\\&lt;br /&gt;
  \end{cases}&lt;br /&gt;
=&lt;br /&gt;
&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
: &amp;lt;math&amp;gt;&lt;br /&gt;
=&lt;br /&gt;
  \begin{cases}&lt;br /&gt;
    S(mins) = n^2(k-1) - \frac{1}{2}(nk^2 - nk) + n - k &amp;amp; \quad\\&lt;br /&gt;
    S(summs) = n^2k - \frac{1}{2}(nk^2 + nk - k^2 + k ) &amp;amp; \quad\\&lt;br /&gt;
  \end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Таким образом, сложность фазы BUILD есть &amp;lt;math&amp;gt;O(kn^2)&amp;lt;/math&amp;gt; как по количеству найденных минимумов, так и по количеству операций сложения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
На основании формулы из описания &#039;&#039;&#039;вычислительного ядра фазы SWAP&#039;&#039;&#039; определим сложность вычисления целевой функции &amp;lt;math&amp;gt;F^i&amp;lt;/math&amp;gt; с использованием оптимизации процесса нахождения минимума (см. раздел [[#Вычислительное ядро алгоритма|Вычислительное ядро алгоритма]]). Количество операций равно:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;S = ( ( (1 mins)*(n-1) + (n-1) summs )*(n-k) + n*((k-1-1) mins) )*k \Rightarrow&amp;lt;/math&amp;gt; &amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\Rightarrow S =&lt;br /&gt;
  \begin{cases}&lt;br /&gt;
    S(mins) = ( ((1 mins)*(n-1) )*(n-k) + n*((k-1-1) mins) )*k = kn^2 - 3nk + k^2 &amp;amp; \quad\\&lt;br /&gt;
    S(summs) = ( ( (n-1) summs )*(n-k) )*k = (n-1)(n-k)k &amp;amp; \quad\\&lt;br /&gt;
  \end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Таким образом, сложность одной итерации фазы SWAP есть &amp;lt;math&amp;gt;O(kn^2)&amp;lt;/math&amp;gt; как по количеству найденных минимумов, так и по количеству операция сложения.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Полученные оценки позволяют говорить о том, что PAM относится к алгоритмам &#039;&#039;&#039;с квадратичной сложностью&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Основная вычислительная сложность алгоритма PAM приходится на фазу SWAP, т.к. сложность одной её итерации сопоставима со сложностью всей фазы BUILD, однако SWAP может содержать в себе огромное число итераций.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
&lt;br /&gt;
==== Информационный граф фазы BUILD ====&lt;br /&gt;
 &lt;br /&gt;
Опишем граф фазы BUILD как аналитически, так и в виде рисунка.&lt;br /&gt;
 &lt;br /&gt;
&#039;&#039;Граф состоит из шести групп вершин&#039;&#039;:&lt;br /&gt;
 &lt;br /&gt;
# Операция M, соответствующая &#039;&#039;&#039;первой&#039;&#039;&#039; группе вершин, осуществляет изменение множества медоидов:&lt;br /&gt;
#:: &amp;lt;math&amp;gt;M_{It} = M_{It-1} \cup \overline{x}_{m_{It}}, &amp;lt;/math&amp;gt; где &amp;lt;math&amp;gt;\overline{x}_{m_{It}} = \overline{x}_{o_{It}}.&amp;lt;/math&amp;gt;&lt;br /&gt;
#: Единственная координата &amp;lt;math&amp;gt;It&amp;lt;/math&amp;gt; (номер итерации), соответствующая каждой из вершин, меняется в диапазоне &amp;lt;math&amp;gt;[1; k],&amp;lt;/math&amp;gt; принимая все целочисленные значения.&lt;br /&gt;
#: Аргументами операции являются:&lt;br /&gt;
#:* &amp;lt;math&amp;gt;\overline{x}_{o_{It}}&amp;lt;/math&amp;gt; - результат срабатывания операции, соответствующей вершине из пятой группы с координатой &amp;lt;math&amp;gt;It,&amp;lt;/math&amp;gt;&lt;br /&gt;
#:* &amp;lt;math&amp;gt;M_{It-1}&amp;lt;/math&amp;gt; - множество медоидов:&lt;br /&gt;
#:** при &amp;lt;math&amp;gt;It = 1 &amp;lt;/math&amp;gt; - входное данное алгоритма;&lt;br /&gt;
#:** при &amp;lt;math&amp;gt;1&amp;lt; It \leq k &amp;lt;/math&amp;gt; -  результат срабатывания операции, соответствующей вершине из первой группы с координатой &amp;lt;math&amp;gt;It-1.&amp;lt;/math&amp;gt;&lt;br /&gt;
#: Результат срабатывания операции является:&lt;br /&gt;
#:* при &amp;lt;math&amp;gt;It &amp;lt; k &amp;lt;/math&amp;gt; - &#039;&#039;промежуточным данным&#039;&#039; алгоритма;&lt;br /&gt;
#:* при &amp;lt;math&amp;gt;It = k &amp;lt;/math&amp;gt; - &#039;&#039;выходным данным&#039;&#039; фазы BUILD.&lt;br /&gt;
#:&lt;br /&gt;
#: &amp;lt;br&amp;gt;&lt;br /&gt;
#:&lt;br /&gt;
# Операция O, соответствующая &#039;&#039;&#039;второй&#039;&#039;&#039; группе вершин, осуществляет изменение множества не-медоидов:&lt;br /&gt;
#:: &amp;lt;math&amp;gt;O_{It} = O_{It-1} \backslash \overline{x}_{o_{It}}.&amp;lt;/math&amp;gt;&lt;br /&gt;
#: Единственная координата &amp;lt;math&amp;gt;It&amp;lt;/math&amp;gt;, соответствующая каждой из вершин, меняется в диапазоне &amp;lt;math&amp;gt;[1; k],&amp;lt;/math&amp;gt; принимая все целочисленные значения.&lt;br /&gt;
#: Аргументами операции являются:&lt;br /&gt;
#:* &amp;lt;math&amp;gt;\overline{x}_{o_{It}}&amp;lt;/math&amp;gt; - результат срабатывания операции, соответствующей вершине из пятой группы с координатой &amp;lt;math&amp;gt;It,&amp;lt;/math&amp;gt;&lt;br /&gt;
#:* &amp;lt;math&amp;gt;O_{It-1}&amp;lt;/math&amp;gt; - множество не-медоидов:&lt;br /&gt;
#:** при &amp;lt;math&amp;gt;It = 1 &amp;lt;/math&amp;gt; - входное данное алгоритма;&lt;br /&gt;
#:** при &amp;lt;math&amp;gt;1&amp;lt; It \leq k &amp;lt;/math&amp;gt; -  результат срабатывания операции, соответствующей вершине из второй группы с координатой &amp;lt;math&amp;gt;It-1.&amp;lt;/math&amp;gt;&lt;br /&gt;
#: Результат срабатывания операции является:&lt;br /&gt;
#:* при &amp;lt;math&amp;gt;It &amp;lt; k &amp;lt;/math&amp;gt; - &#039;&#039;промежуточным данным&#039;&#039; алгоритма;&lt;br /&gt;
#:* при &amp;lt;math&amp;gt;It = k &amp;lt;/math&amp;gt; - &#039;&#039;выходным данным&#039;&#039; фазы BUILD.&lt;br /&gt;
#:&lt;br /&gt;
#: &amp;lt;br&amp;gt;&lt;br /&gt;
#:&lt;br /&gt;
# Операция, соответствующая &#039;&#039;&#039;третьей&#039;&#039;&#039; группе вершин, выглядит следующим образом:&lt;br /&gt;
#:: &amp;lt;math&amp;gt;\overline{c}=\overline{c}_{x_{o_p} } =  \begin{cases} \{ \rho (x_{o_p}, x_j ) \| 1 \leq j \leq n \}, It=1 &amp;amp; \quad\\ \{ \min ( \overline{MIN}^{(j)}, \rho (x_{o_p}, x_j) ) \| 1 \leq j \leq n \}, 1&amp;lt;It \leq k &amp;amp; \quad\\  \end{cases} .&amp;lt;/math&amp;gt;&lt;br /&gt;
#: Координаты вершин:&lt;br /&gt;
#:* &amp;lt;math&amp;gt;It&amp;lt;/math&amp;gt; - меняется в диапазоне &amp;lt;math&amp;gt;[1; k],&amp;lt;/math&amp;gt; принимая все целочисленные значения;&lt;br /&gt;
#:* &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; - меняется в диапазоне &amp;lt;math&amp;gt;[1; n-It+1],&amp;lt;/math&amp;gt; принимая все целочисленные значения.&lt;br /&gt;
#: Аргументами операции являются:&lt;br /&gt;
#:* при &amp;lt;math&amp;gt;It = 1:&amp;lt;/math&amp;gt;&lt;br /&gt;
#:** &amp;lt;math&amp;gt;\overline{x}_{o_p}&amp;lt;/math&amp;gt; - входное данное алгоритма;&lt;br /&gt;
#:* при &amp;lt;math&amp;gt;1 &amp;lt; It \leq k:&amp;lt;/math&amp;gt;&lt;br /&gt;
#:**&amp;lt;math&amp;gt;\overline{x}_{o_p}&amp;lt;/math&amp;gt; - результат срабатывания операции, соответствующей вершине из второй группы с координатой &amp;lt;math&amp;gt;It-1;&amp;lt;/math&amp;gt;&lt;br /&gt;
#:**&amp;lt;math&amp;gt;\overline{MIN}&amp;lt;/math&amp;gt; - результат срабатывания операции, соответствующей вершине из шестой группы с координатой &amp;lt;math&amp;gt;It-1.&amp;lt;/math&amp;gt;&lt;br /&gt;
#: Результат срабатывания операции является &#039;&#039;промежуточным данным&#039;&#039; алгоритма.&lt;br /&gt;
#:&lt;br /&gt;
#: &amp;lt;br&amp;gt;&lt;br /&gt;
#:&lt;br /&gt;
# Операция S, соответствующая &#039;&#039;&#039;четвертой&#039;&#039;&#039; группе вершин, выглядит следующим образом:&lt;br /&gt;
#:: &amp;lt;math&amp;gt;S = \sum_{j = 1}^{n} \overline {c}^{(j)}.&amp;lt;/math&amp;gt;&lt;br /&gt;
#: Координаты вершин:&lt;br /&gt;
#:* &amp;lt;math&amp;gt;It&amp;lt;/math&amp;gt; - меняется в диапазоне &amp;lt;math&amp;gt;[1; k],&amp;lt;/math&amp;gt; принимая все целочисленные значения;&lt;br /&gt;
#:* &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; - меняется в диапазоне &amp;lt;math&amp;gt;[1; n-It+1],&amp;lt;/math&amp;gt; принимая все целочисленные значения.&lt;br /&gt;
#: Аргументами операции являются:&lt;br /&gt;
#:* &amp;lt;math&amp;gt;\overline{c}_{ x_{o_p} }&amp;lt;/math&amp;gt; - результат срабатывания операции, соответствующей вершине из третьей группы с координатами &amp;lt;math&amp;gt; It, p.&amp;lt;/math&amp;gt;&lt;br /&gt;
#: Результат срабатывания операции является &#039;&#039;промежуточным данным&#039;&#039; алгоритма.&lt;br /&gt;
#:&lt;br /&gt;
#: &amp;lt;br&amp;gt;&lt;br /&gt;
#:&lt;br /&gt;
# Операция M1, соответствующая &#039;&#039;&#039;пятой&#039;&#039;&#039; группе вершин, выглядит следующим образом:&lt;br /&gt;
#:: &amp;lt;math&amp;gt;M1 = (F^{It}; x_{o_{It}}),&amp;lt;/math&amp;gt; где &amp;lt;math&amp;gt; \begin{cases}&lt;br /&gt;
F^{It} = \min_{x_{o_p} \in O_{It-1}} S &amp;amp; \quad\\&lt;br /&gt;
x_{o_{It}} = \arg F^{It} &amp;amp; \quad\\&lt;br /&gt;
\end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
#: Координаты вершин:&lt;br /&gt;
#:* &amp;lt;math&amp;gt;It&amp;lt;/math&amp;gt; - меняется в диапазоне &amp;lt;math&amp;gt;[1; k],&amp;lt;/math&amp;gt; принимая все целочисленные значения.&lt;br /&gt;
#: Аргументами операции являются:&lt;br /&gt;
#:* &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; - результаты срабатывания операций, соответствующих вершинам из четвертой группы с первой координатой &amp;lt;math&amp;gt;It,&amp;lt;/math&amp;gt; всего &amp;lt;math&amp;gt;n-It+1&amp;lt;/math&amp;gt; величина.&lt;br /&gt;
#: Результат срабатывания операции является:&lt;br /&gt;
#:* при &amp;lt;math&amp;gt;It &amp;lt; k &amp;lt;/math&amp;gt; - &#039;&#039;промежуточным данным&#039;&#039; алгоритма;&lt;br /&gt;
#:* при &amp;lt;math&amp;gt;It = k &amp;lt;/math&amp;gt; - &#039;&#039;выходным данным&#039;&#039; фазы BUILD.&lt;br /&gt;
#:&lt;br /&gt;
#: &amp;lt;br&amp;gt;&lt;br /&gt;
#:&lt;br /&gt;
# Операция MIN, соответствующая &#039;&#039;&#039;шестой&#039;&#039;&#039; группе вершин, выглядит следующим образом:&lt;br /&gt;
#:: &amp;lt;math&amp;gt;\overline{MIN}=\overline{MIN}_{It,x_{m_{It}} } =  \begin{cases}&lt;br /&gt;
\{ \rho (x_{m_{It}            }, x_j ) \| 1 \leq j \leq n \}, It=1 &amp;amp; \quad\\&lt;br /&gt;
\{ \min ( \overline{MIN}^{(j)}, \rho (x_{m_{It}}, x_j) ) \| 1 \leq j \leq n \}, 1&amp;lt;It \leq k &amp;amp; \quad\\&lt;br /&gt;
 \end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
#: Координаты вершин:&lt;br /&gt;
#:* &amp;lt;math&amp;gt;It&amp;lt;/math&amp;gt; - меняется в диапазоне &amp;lt;math&amp;gt;[1; k-1],&amp;lt;/math&amp;gt; принимая все целочисленные значения.&lt;br /&gt;
#: Аргументами операции являются:&lt;br /&gt;
#:* &amp;lt;math&amp;gt;\overline{MIN}_{It-1,x_{m_{It-1}}} &amp;lt;/math&amp;gt; - результат срабатывания операции, соответствующей вершине из шестой группы с координатой &amp;lt;math&amp;gt;It-1;&amp;lt;/math&amp;gt;&lt;br /&gt;
#:* &amp;lt;math&amp;gt;x_{m_{It}} =  x_{o_{It}} &amp;lt;/math&amp;gt; - результат срабатывания операции, соответствующей вершине из пятой группы с координатой &amp;lt;math&amp;gt;It.&amp;lt;/math&amp;gt;&lt;br /&gt;
#: Результат срабатывания операции является &#039;&#039;промежуточным данным&#039;&#039; алгоритма.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Описанный граф в общем случае представлен на Рис.1, отображен шаг с номером &amp;lt;math&amp;gt;It, 1&amp;lt;It&amp;lt;k&amp;lt;/math&amp;gt; фазы BUILD.&lt;br /&gt;
Обозначения:&lt;br /&gt;
# вершины первой группы обозначены фиолетовым цветом и подписаны как &amp;lt;math&amp;gt;M;&amp;lt;/math&amp;gt;&lt;br /&gt;
# вершины  второй группы обозначены синим цветом и подписаны как &amp;lt;math&amp;gt;O;&amp;lt;/math&amp;gt;&lt;br /&gt;
# вершины третьей группы обозначены жёлтым цветом и подписаны как &amp;lt;math&amp;gt;\overline{c}_{x_{o_p} };&amp;lt;/math&amp;gt;&lt;br /&gt;
# вершины четвертой группы обозначены серым цветом и подписаны как &amp;lt;math&amp;gt;S;&amp;lt;/math&amp;gt;&lt;br /&gt;
# вершины пятой группы обозначены зеленым цветом и подписаны как &amp;lt;math&amp;gt;M1;&amp;lt;/math&amp;gt;&lt;br /&gt;
# вершины шестой группы обозначены красным цветом и подписаны как &amp;lt;math&amp;gt;MIN;&amp;lt;/math&amp;gt;&lt;br /&gt;
# синим дугам сопоставлены метки, отражающие данные, используемые в соответствующих жёлтых вершинах.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[file:Pam build 1.png|thumb|center|800px|Рисунок 1. Граф фазы BUILD алгоритма.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
На Рис.2 представлен граф фазы BUILD для случая &amp;lt;math&amp;gt;n=6, k=3.&amp;lt;/math&amp;gt; Вершины, соответствующие операциям, получающим входные данные и производящим выходные данные, увеличены и выделены толстыми границами.&lt;br /&gt;
&lt;br /&gt;
[[file:Pam build 2.png|thumb|center|1100px|Рисунок 2. Граф фазы BUILD алгоритма для n = 6, k = 3. ]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Информационный граф фазы SWAP ====&lt;br /&gt;
 &lt;br /&gt;
Опишем граф фазы SWAP как аналитически, так и в виде рисунка.&lt;br /&gt;
 &lt;br /&gt;
&#039;&#039;Граф состоит из семи групп вершин&#039;&#039;:&lt;br /&gt;
 &lt;br /&gt;
# Операция M, соответствующая &#039;&#039;&#039;первой&#039;&#039;&#039; группе вершин, осуществляет изменение множества медоидов.&lt;br /&gt;
#: Единственная координата &amp;lt;math&amp;gt;It&amp;lt;/math&amp;gt; (номер итерации), соответствующая каждой из вершин, меняется в диапазоне &amp;lt;math&amp;gt;[1; T),&amp;lt;/math&amp;gt; принимая все целочисленные значения, где:&lt;br /&gt;
#:: &amp;lt;math&amp;gt;T\in \N&amp;lt;/math&amp;gt; - количество выполнений фазы SWAP во время работы алгоритма PAM.&lt;br /&gt;
#: Аргументами операции являются:&lt;br /&gt;
#:* результат срабатывания операции, соответствующей вершине из седьмой группы с координатой &amp;lt;math&amp;gt;It,&amp;lt;/math&amp;gt;&lt;br /&gt;
#:* &amp;lt;math&amp;gt;M_{It-1}&amp;lt;/math&amp;gt; - множество медоидов:&lt;br /&gt;
#:** при &amp;lt;math&amp;gt;It = 1 &amp;lt;/math&amp;gt; - результат выполнения фазы BUILD;&lt;br /&gt;
#:** при &amp;lt;math&amp;gt;1&amp;lt; It &amp;lt; T &amp;lt;/math&amp;gt; -  результат срабатывания операции, соответствующей вершине из первой группы с координатой &amp;lt;math&amp;gt;It-1.&amp;lt;/math&amp;gt;&lt;br /&gt;
#: Результат срабатывания операции является:&lt;br /&gt;
#:* при &amp;lt;math&amp;gt;It &amp;lt; T -1 &amp;lt;/math&amp;gt; - &#039;&#039;промежуточным данным&#039;&#039; алгоритма;&lt;br /&gt;
#:* при &amp;lt;math&amp;gt;It = T - 1&amp;lt;/math&amp;gt; - &#039;&#039;выходным данным&#039;&#039; фазы SWAP.&lt;br /&gt;
#:&lt;br /&gt;
#: &amp;lt;br&amp;gt;&lt;br /&gt;
#:&lt;br /&gt;
# Операция O, соответствующая &#039;&#039;&#039;второй&#039;&#039;&#039; группе вершин, осуществляет изменение множества не-медоидов.&lt;br /&gt;
#: Единственная координата &amp;lt;math&amp;gt;It&amp;lt;/math&amp;gt;, соответствующая каждой из вершин, меняется в диапазоне &amp;lt;math&amp;gt;[1; T),&amp;lt;/math&amp;gt; принимая все целочисленные значения, где:&lt;br /&gt;
#:: &amp;lt;math&amp;gt;T\in \N&amp;lt;/math&amp;gt; - количество выполнений фазы SWAP во время работы алгоритма PAM.&lt;br /&gt;
#: Аргументами операции являются:&lt;br /&gt;
#:* результат срабатывания операции, соответствующей вершине из седьмой группы с координатой &amp;lt;math&amp;gt;It,&amp;lt;/math&amp;gt;&lt;br /&gt;
#:* &amp;lt;math&amp;gt;O_{It-1}&amp;lt;/math&amp;gt; - множество не-медоидов:&lt;br /&gt;
#:** при &amp;lt;math&amp;gt;It = 1 &amp;lt;/math&amp;gt; - результат выполнения фазы BUILD;&lt;br /&gt;
#:** при &amp;lt;math&amp;gt;1&amp;lt; It &amp;lt; T &amp;lt;/math&amp;gt; -  результат срабатывания операции, соответствующей вершине из второй группы с координатой &amp;lt;math&amp;gt;It-1.&amp;lt;/math&amp;gt;&lt;br /&gt;
#: Результат срабатывания операции является &#039;&#039;промежуточным данным&#039;&#039; алгоритма.&lt;br /&gt;
#:&lt;br /&gt;
#: &amp;lt;br&amp;gt;&lt;br /&gt;
#:&lt;br /&gt;
# Операция, соответствующая &#039;&#039;&#039;третьей&#039;&#039;&#039; группе вершин, выглядит следующим образом:&lt;br /&gt;
#:: &amp;lt;math&amp;gt;\overline{a}=\overline{a}_{x_{m_i} } = \{ \min_{ x_{m_l} \in M  \backslash \{x_{m_i}\} }  \rho ( x_{m_l},x_j ) \| 1 \leq j \leq n \}.&amp;lt;/math&amp;gt;&lt;br /&gt;
#: Координаты вершин:&lt;br /&gt;
#:* &amp;lt;math&amp;gt;It&amp;lt;/math&amp;gt; - меняется в диапазоне &amp;lt;math&amp;gt;[1; T],&amp;lt;/math&amp;gt; принимая все целочисленные значения;&lt;br /&gt;
#:* &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - меняется в диапазоне &amp;lt;math&amp;gt;[1; k],&amp;lt;/math&amp;gt; принимая все целочисленные значения.&lt;br /&gt;
#: Аргументом операции является &amp;lt;math&amp;gt;\overline{x}_{m_i}:&amp;lt;/math&amp;gt;&lt;br /&gt;
#:* при &amp;lt;math&amp;gt;It = 1&amp;lt;/math&amp;gt; - результат выполнения фазы BUILD;&lt;br /&gt;
#:* при &amp;lt;math&amp;gt;It &amp;gt; 1&amp;lt;/math&amp;gt; - результат срабатывания операции, соответствующей вершине из первой группы с координатой &amp;lt;math&amp;gt;It-1.&amp;lt;/math&amp;gt;&lt;br /&gt;
#: Результат срабатывания операции является &#039;&#039;промежуточным данным&#039;&#039; алгоритма.&lt;br /&gt;
#:&lt;br /&gt;
#: &amp;lt;br&amp;gt;&lt;br /&gt;
#:&lt;br /&gt;
# Операция, соответствующая &#039;&#039;&#039;четвертой&#039;&#039;&#039; группе вершин, выглядит следующим образом:&lt;br /&gt;
#:: &amp;lt;math&amp;gt;\overline{b}=\overline{b}_{x_{m_i} x_{o_p} } =  \{ \min (\overline{a}_{ x_{m_i}}^{(j)}, \rho ( x_{o_p},x_j )) \| 1 \leq j \leq n \}.&amp;lt;/math&amp;gt;&lt;br /&gt;
#: Координаты вершин:&lt;br /&gt;
#:* &amp;lt;math&amp;gt;It&amp;lt;/math&amp;gt; - меняется в диапазоне &amp;lt;math&amp;gt;[1; T],&amp;lt;/math&amp;gt; принимая все целочисленные значения;&lt;br /&gt;
#:* &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - меняется в диапазоне &amp;lt;math&amp;gt;[1; k],&amp;lt;/math&amp;gt; принимая все целочисленные значения;&lt;br /&gt;
#:* &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; - меняется в диапазоне &amp;lt;math&amp;gt;[1; n-k],&amp;lt;/math&amp;gt; принимая все целочисленные значения.&lt;br /&gt;
#: Аргументами операции являются:&lt;br /&gt;
#:* &amp;lt;math&amp;gt;\overline{x}_{o_p}:&amp;lt;/math&amp;gt;&lt;br /&gt;
#:** при &amp;lt;math&amp;gt;It = 1&amp;lt;/math&amp;gt; - результат выполнения фазы BUILD;&lt;br /&gt;
#:** при &amp;lt;math&amp;gt;It &amp;gt; 1&amp;lt;/math&amp;gt; - результат срабатывания операции, соответствующей вершине из второй группы с координатой &amp;lt;math&amp;gt;It-1&amp;lt;/math&amp;gt;&lt;br /&gt;
#:* &amp;lt;math&amp;gt;\overline{a}_{x_{m_i}}&amp;lt;/math&amp;gt; - результат срабатывания операции, соответствующей вершине из третьей группы с координатами &amp;lt;math&amp;gt;It, i.&amp;lt;/math&amp;gt;&lt;br /&gt;
#: Результат срабатывания операции является &#039;&#039;промежуточным данным&#039;&#039; алгоритма.&lt;br /&gt;
#:&lt;br /&gt;
#: &amp;lt;br&amp;gt;&lt;br /&gt;
#:&lt;br /&gt;
# Операция S, соответствующая &#039;&#039;&#039;пятой&#039;&#039;&#039; группе вершин, выглядит следующим образом:&lt;br /&gt;
#:: &amp;lt;math&amp;gt;S = \sum_{j = 1}^{n} \overline {b}^{(j)}.&amp;lt;/math&amp;gt;&lt;br /&gt;
#: Координаты вершин:&lt;br /&gt;
#:* &amp;lt;math&amp;gt;It&amp;lt;/math&amp;gt; - меняется в диапазоне &amp;lt;math&amp;gt;[1; T],&amp;lt;/math&amp;gt; принимая все целочисленные значения;&lt;br /&gt;
#:* &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - меняется в диапазоне &amp;lt;math&amp;gt;[1; k],&amp;lt;/math&amp;gt; принимая все целочисленные значения;&lt;br /&gt;
#:* &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; - меняется в диапазоне &amp;lt;math&amp;gt;[1; n-k],&amp;lt;/math&amp;gt; принимая все целочисленные значения.&lt;br /&gt;
#: Аргументами операции являются:&lt;br /&gt;
#:* &amp;lt;math&amp;gt;\overline{b}_{x_{m_i} x_{o_p} }&amp;lt;/math&amp;gt; - результат срабатывания операции, соответствующей вершине из четвертой группы с координатами &amp;lt;math&amp;gt;It, i, p.&amp;lt;/math&amp;gt;&lt;br /&gt;
#: Результат срабатывания операции является &#039;&#039;промежуточным данным&#039;&#039; алгоритма.&lt;br /&gt;
#:&lt;br /&gt;
#: &amp;lt;br&amp;gt;&lt;br /&gt;
#:&lt;br /&gt;
# Операция M1, соответствующая &#039;&#039;&#039;шестой&#039;&#039;&#039; группе вершин, выглядит следующим образом:&lt;br /&gt;
#:: &amp;lt;math&amp;gt;M1 = (F_{x_{o_p}}^{It}; x_{o_p}),&amp;lt;/math&amp;gt; где &amp;lt;math&amp;gt; \begin{cases}&lt;br /&gt;
F_{x_{o_p}}^{It} = \min_{x_{o_p} \in O} S &amp;amp; \quad\\&lt;br /&gt;
x_{o_p} = \arg F_{x_{o_p}}^{It} &amp;amp; \quad\\&lt;br /&gt;
\end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
#: Координаты вершин:&lt;br /&gt;
#:* &amp;lt;math&amp;gt;It&amp;lt;/math&amp;gt; - меняется в диапазоне &amp;lt;math&amp;gt;[1; T],&amp;lt;/math&amp;gt; принимая все целочисленные значения;&lt;br /&gt;
#:* &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; - меняется в диапазоне &amp;lt;math&amp;gt;[1; k],&amp;lt;/math&amp;gt; принимая все целочисленные значения.&lt;br /&gt;
#: Аргументами операции являются:&lt;br /&gt;
#:* &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; - результаты срабатывания операций, соответствующих вершинам из пятой группы с первыми двумя координатами &amp;lt;math&amp;gt;It, i,&amp;lt;/math&amp;gt; всего &amp;lt;math&amp;gt;n-k&amp;lt;/math&amp;gt; величин.&lt;br /&gt;
#: Результат срабатывания операции является &#039;&#039;промежуточным данным&#039;&#039; алгоритма.&lt;br /&gt;
#:&lt;br /&gt;
#: &amp;lt;br&amp;gt;&lt;br /&gt;
#:&lt;br /&gt;
# Операция M2, соответствующая &#039;&#039;&#039;седьмой&#039;&#039;&#039; группе вершин, выглядит следующим образом:&lt;br /&gt;
#:: &amp;lt;math&amp;gt;M2 = (F_{x_{o_p}, x_{m_i}}^{It}; x_{m_i}; x_{o_p}),&amp;lt;/math&amp;gt; где &amp;lt;math&amp;gt;\begin{cases}&lt;br /&gt;
F_{x_{o_p}, x_{m_i}}^{It} = \min (\min_{x_{m_i} \in M} (F_{x_{o_p}}^{It}), M2_{It-1}) &amp;amp; \quad\\&lt;br /&gt;
x_{m_i} = \arg \min_{x_{m_i} \in M} M1 &amp;amp; \quad\\&lt;br /&gt;
\end{cases}&amp;lt;/math&amp;gt;&lt;br /&gt;
#: Координаты вершин:&lt;br /&gt;
#:* &amp;lt;math&amp;gt;It&amp;lt;/math&amp;gt; - меняется в диапазоне &amp;lt;math&amp;gt;[1; T],&amp;lt;/math&amp;gt; принимая все целочисленные значения.&lt;br /&gt;
#: Аргументами операции являются:&lt;br /&gt;
#:* &amp;lt;math&amp;gt;M1 = (F_{x_{o_p}}^{It}; x_{o_p})&amp;lt;/math&amp;gt; - результаты срабатывания операций, соответствующих вершинам из шестой группы с координатами &amp;lt;math&amp;gt;It, i,&amp;lt;/math&amp;gt; всего &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; величин;&lt;br /&gt;
#:* &amp;lt;math&amp;gt;M2_{It-1}:&amp;lt;/math&amp;gt;&lt;br /&gt;
#:** при &amp;lt;math&amp;gt;It = 1&amp;lt;/math&amp;gt; - результат выполнения фазы BUILD;&lt;br /&gt;
#:** при &amp;lt;math&amp;gt;It &amp;gt; 1&amp;lt;/math&amp;gt; - результаты срабатывания операции, соответствующей вершине из седьмой группы с координатой &amp;lt;math&amp;gt;It-1;&amp;lt;/math&amp;gt;&lt;br /&gt;
#: Результат срабатывания операции является:&lt;br /&gt;
#:* при &amp;lt;math&amp;gt;It &amp;lt; T&amp;lt;/math&amp;gt; - &#039;&#039;промежуточным данным&#039;&#039; алгоритма;&lt;br /&gt;
#:* при &amp;lt;math&amp;gt;It = T&amp;lt;/math&amp;gt; - &#039;&#039;выходным данным&#039;&#039; фазы SWAP.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Описанный граф в общем случае представлен на Рис.3, отображена одна итерация фазы SWAP.&lt;br /&gt;
Обозначения:&lt;br /&gt;
# вершины первой группы обозначены фиолетовым цветом и подписаны как &amp;lt;math&amp;gt;M;&amp;lt;/math&amp;gt;&lt;br /&gt;
# вершины второй группы обозначены синим цветом и подписаны как &amp;lt;math&amp;gt;O;&amp;lt;/math&amp;gt;&lt;br /&gt;
# вершины третьей группы обозначены желтым цветом и подписаны как &amp;lt;math&amp;gt;\overline{a}_{x_{m_i} };&amp;lt;/math&amp;gt;&lt;br /&gt;
# вершины четвертой группы обозначены оранжевым цветом и подписаны как &amp;lt;math&amp;gt;\overline{b}_{x_{m_i o_p} };&amp;lt;/math&amp;gt;&lt;br /&gt;
# вершины пятой группы обозначены серым цветом и подписаны как &amp;lt;math&amp;gt;S;&amp;lt;/math&amp;gt;&lt;br /&gt;
# вершины шестой группы обозначены зеленым цветом и подписаны как &amp;lt;math&amp;gt;M1;&amp;lt;/math&amp;gt;&lt;br /&gt;
# вершины седьмой группы обозначены красным цветом и подписаны как &amp;lt;math&amp;gt;M2;&amp;lt;/math&amp;gt;&lt;br /&gt;
# синим дугам сопоставлены метки, отражающие данные, используемые в соответствующих оранжевых вершинах;&lt;br /&gt;
# фиолетовым дугам сопоставлены метки, отражающие данные, используемые в соответствующих жёлтых вершинах.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[file:Pam swap 1.png|thumb|center|1100px|Рисунок 3. Граф фазы SWAP алгоритма.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
На Рис.4 представлен граф фазы SWAP для случая &amp;lt;math&amp;gt;n=6, k=2, T=3.&amp;lt;/math&amp;gt; Вершины, соответствующие операциям, получающим входные данные и производящим выходные данные, увеличены и выделены толстыми границами.&lt;br /&gt;
&lt;br /&gt;
[[file:Pam swap 2.png|thumb|center|1100px|Рисунок 4. Граф фазы SWAP алгоритма для n = 6, k = 2, T = 3.]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
При параллельной реализации алгоритма PAM будем рассматривать параллельные варианты фазы BUILD и SWAP ([[#Возможная параллельная реализация алгоритма PAM|возможная параллельная реализация]]). Покажем, что сложность фазы BUILD сопоставима со сложностью одной итерации фазы SWAP.&lt;br /&gt;
&lt;br /&gt;
Оценки последовательной сложности фаз BUILD и SWAP приведены в параграфе &amp;quot;[[#Последовательная сложность алгоритма|Последовательная сложность алгоритма]]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Ресурс параллелизма фазы BUILD ====&lt;br /&gt;
&lt;br /&gt;
Для решения задачи кластеризации методом PAM в параллельном варианте фазы BUILD в предположении доступности неограниченного числа процессов для одной итерации необходимо выполнить:&lt;br /&gt;
*  1 ярус с нахождением &amp;lt;math&amp;gt;\overline{c}:&amp;lt;/math&amp;gt;&lt;br /&gt;
** &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; операций нахождения минимального из двух элементов при &amp;lt;math&amp;gt;It &amp;gt; 1&amp;lt;/math&amp;gt;;&lt;br /&gt;
* 1 ярус с нахождением суммы &amp;lt;math&amp;gt;S:&amp;lt;/math&amp;gt;&lt;br /&gt;
** &amp;lt;math&amp;gt;n-1&amp;lt;/math&amp;gt; операцию сложения;&lt;br /&gt;
* 1 ярус с нахождением значений элемента &amp;lt;math&amp;gt;M1:&amp;lt;/math&amp;gt;&lt;br /&gt;
** &amp;lt;math&amp;gt;n-It&amp;lt;/math&amp;gt; операций нахождения минимального из двух элементов;&lt;br /&gt;
* 1 ярус с нахождением минимального элемента &amp;lt;math&amp;gt;\overline{MIN}:&amp;lt;/math&amp;gt;&lt;br /&gt;
** &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; операций нахождения минимального из двух элементов при &amp;lt;math&amp;gt;It&amp;gt;1;&amp;lt;/math&amp;gt;&lt;br /&gt;
* 1 ярус с изменением множеств медоидов и не-медоидов (не выполняются операции рассматриваемых типов).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Таким образом, параллельная сложность одного шага фазы BUILD равна: &lt;br /&gt;
* &amp;lt;math&amp;gt;n-1&amp;lt;/math&amp;gt; операция сложения;&lt;br /&gt;
* &amp;lt;math&amp;gt;n-It&amp;lt;/math&amp;gt; операций нахождения минимального из двух элементов при &amp;lt;math&amp;gt;It=1;&amp;lt;/math&amp;gt;&lt;br /&gt;
* &amp;lt;math&amp;gt;3n-It&amp;lt;/math&amp;gt; операций нахождения минимального из двух элементов при &amp;lt;math&amp;gt;It&amp;gt;1.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Параллельная сложность фазы BUILD при числе кластеров &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; равна: &lt;br /&gt;
* &amp;lt;math&amp;gt;kn-k&amp;lt;/math&amp;gt; операция сложения;&lt;br /&gt;
* &amp;lt;math&amp;gt;3kn - 2n - \frac{1}{2}k^2 - \frac{1}{2}k&amp;lt;/math&amp;gt; операций нахождения минимального из двух элементов.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В параллельном варианте, по сравнению с последовательным, при &amp;lt;math&amp;gt;k, n \to \infty&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;O(kn)&amp;lt;/math&amp;gt; против &amp;lt;math&amp;gt;O(kn^2).&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Соотношение количества сложений и взятий минимума для фазы BUILD является постоянным и стремится к &amp;lt;math&amp;gt;3,&amp;lt;/math&amp;gt; при &amp;lt;math&amp;gt;k, n \to \infty.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Максимальная ширина яруса достигается при вычислении &amp;lt;math&amp;gt;\overline {c}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; и равна &amp;lt;math&amp;gt;n-It+1&amp;lt;/math&amp;gt; для шага &amp;lt;math&amp;gt;It&amp;lt;/math&amp;gt; фазы BUILD. Максимальная ширина яруса при рассмотрении всей фазы есть &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; и достигается на первом шаге.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Ресурс параллелизма фазы SWAP ====&lt;br /&gt;
&lt;br /&gt;
Для решения задачи кластеризации методом PAM в параллельном варианте фазы SWAP в предположении доступности неограниченного числа процессов для одной итерации необходимо выполнить:&lt;br /&gt;
* 1 ярус с нахождением &amp;lt;math&amp;gt;\overline {a}:&amp;lt;/math&amp;gt;&lt;br /&gt;
** &amp;lt;math&amp;gt;n(k-1)&amp;lt;/math&amp;gt; операций нахождения минимального из двух элементов;&lt;br /&gt;
* 1 ярус с нахождением &amp;lt;math&amp;gt;\overline {b}:&amp;lt;/math&amp;gt;&lt;br /&gt;
** &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; операций нахождения минимального из двух элементов;&lt;br /&gt;
* 1 ярус с нахождением суммы &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;:&lt;br /&gt;
** &amp;lt;math&amp;gt;n-1&amp;lt;/math&amp;gt; операцию сложения;&lt;br /&gt;
* 1 ярус с нахождением минимального элемента &#039;первого&#039; вида &amp;lt;math&amp;gt;(M1 = \min_{x_{o_p} \in O} S):&amp;lt;/math&amp;gt;&lt;br /&gt;
** &amp;lt;math&amp;gt;n-k-1&amp;lt;/math&amp;gt; операцию нахождения минимального из двух элементов;&lt;br /&gt;
* 1 ярус с нахождением минимального элемента &#039;второго&#039; вида &amp;lt;math&amp;gt;(M2 = \min_{x_{m_i} \in M} M1):&amp;lt;/math&amp;gt;&lt;br /&gt;
** &amp;lt;math&amp;gt;k-1&amp;lt;/math&amp;gt; операцию нахождения минимального из двух элементов;&lt;br /&gt;
* 1 ярус с изменением множеств медоидов и не-медоидов (не выполняются операции рассматриваемых типов).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Таким образом, параллельная сложность одной итерации фазы SWAP равна:&lt;br /&gt;
* &amp;lt;math&amp;gt;n-1&amp;lt;/math&amp;gt; - по количеству операций сложения;&lt;br /&gt;
* &amp;lt;math&amp;gt;kn + n - 2&amp;lt;/math&amp;gt; - по количеству операций нахождений минимума для двух чисел.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В параллельном варианте, по сравнению с последовательным, при &amp;lt;math&amp;gt;k, n \to \infty&amp;lt;/math&amp;gt; количество операций на один порядок меньше по параметру &amp;lt;math&amp;gt;n:&amp;lt;/math&amp;gt;&lt;br /&gt;
: &amp;lt;math&amp;gt;O(kn)&amp;lt;/math&amp;gt; против &amp;lt;math&amp;gt;O(kn^2).&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Соотношение количества сложений и взятий минимума для одной итерации фазы SWAP является постоянным и равным &amp;lt;math&amp;gt;k,&amp;lt;/math&amp;gt; при &amp;lt;math&amp;gt;n \to \infty&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Максимальная ширина яруса достигается при вычислении &amp;lt;math&amp;gt;\overline {b}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; и равна &amp;lt;math&amp;gt;k(n-k).&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
При использовании выбранной модели, в предположении доступности неограниченного числа вычислителей, фаза BUILD при &amp;lt;math&amp;gt;n \to \infty&amp;lt;/math&amp;gt; требует большего количества операций суммирования на порядок &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;, по сравнению с одной итерацией фазы SWAP. В свою очередь, количество операций подсчёта минимума ассимптотически эквивалентны.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Входные данные&#039;&#039;:&lt;br /&gt;
* число &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - количество точек упорядоченного множества &amp;lt;math&amp;gt;X;&amp;lt;/math&amp;gt;&lt;br /&gt;
* число &amp;lt;math&amp;gt;k&amp;lt;/math&amp;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;X&amp;lt;/math&amp;gt; за исключением расстояний вида &amp;lt;math&amp;gt;\rho (x, x)=0, x \in X;&amp;lt;/math&amp;gt;&lt;br /&gt;
&#039;&#039;Объём входных данных&#039;&#039;: &amp;lt;math&amp;gt;n(n-1)&amp;lt;/math&amp;gt; вещественное число и &amp;lt;math&amp;gt;2&amp;lt;/math&amp;gt; целых числа.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Структура хранения данных&#039;&#039;:&lt;br /&gt;
* сразу после считывания входных данных составляется квадратная симметрическая матрица &amp;lt;math&amp;gt;D^{n * n}&amp;lt;/math&amp;gt;, у которой каждый элемент &amp;lt;math&amp;gt;d_{ij}&amp;lt;/math&amp;gt; является вещественным числом - расстоянием &amp;lt;math&amp;gt;\rho (x_i, x_j);&amp;lt;/math&amp;gt;&lt;br /&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;X&amp;lt;/math&amp;gt;, аналогичный массив &amp;lt;math&amp;gt;n-k&amp;lt;/math&amp;gt; целых чисел создаётся для множества не-медоидов &amp;lt;math&amp;gt;O;&amp;lt;/math&amp;gt;&lt;br /&gt;
* для пересылки данных, как правило, используется тройка &amp;lt;math&amp;gt;(F_{x_{m_s}, x_{o_h}}^{i_j}; x_{m_s}; x_{o_h})&amp;lt;/math&amp;gt; или пара &amp;lt;math&amp;gt;(F_{x_{o_h}}^{i_j}; x_{o_h}),&amp;lt;/math&amp;gt; где:&lt;br /&gt;
** &amp;lt;math&amp;gt;x_{m_s}&amp;lt;/math&amp;gt; - целое число, обозначающее порядковый номер элемента множества &amp;lt;math&amp;gt;X;&amp;lt;/math&amp;gt;&lt;br /&gt;
** &amp;lt;math&amp;gt;x_{o_h}&amp;lt;/math&amp;gt; - целое число, обозначающее порядковый номер элемента множества &amp;lt;math&amp;gt;X;&amp;lt;/math&amp;gt;&lt;br /&gt;
** &amp;lt;math&amp;gt;F_{x_{m_s}, x_{o_h}}^{i_j}&amp;lt;/math&amp;gt; - вещественное число, равное минимальному значению целевой функции, вычисленному в текущем контексте.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Выходные данные&#039;&#039;:&lt;br /&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;
* &amp;lt;math&amp;gt;1&amp;lt;/math&amp;gt; вещественное число, являющееся значением целевой функции.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Объём выходных данных&#039;&#039;:&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;  вещественное.&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Соотношение последовательной и параллельной сложности алгоритма является &#039;&#039;линейным&#039;&#039; и равным &amp;lt;math&amp;gt;n.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Вычислительная мощность&#039;&#039; последовательного алгоритма, как отношение числа операций к суммарному объему входных и выходных данных, равна &amp;lt;math&amp;gt;O(T*k).&amp;lt;/math&amp;gt;&lt;br /&gt;
Вычислительная мощность параллельного алгоритма равна &amp;lt;math&amp;gt;O(T*\frac{k}{n}).&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм PAM является &#039;&#039;менее чувствительным&#039;&#039; к выбросам данных, чем алгоритм k-средних. Это связано с использованием медоидов, менее подверженных влиянию таких данных.&amp;lt;ref&amp;gt; Егоров А. В., Куприянова Н. И. Особенности методов кластеризации данных // Известия Южного федерального университета. Технические науки. –2011. T. 124, № 11. –С. 174-177.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Фиксированный способ выбора начальных приближений позволяет говорить о воспроизводимости полученных результатов для последовательной реализации. Для параллельной работы алгоритма подобная воспроизводимость отсутствует, так как из-за &#039;&#039;недетерминированности&#039;&#039; выбора элементов, на которых достигается минимальное значение целевой функции для каждой итерации, итоговое множество медоидов и, следовательно, значение целевой функции может меняться.&lt;br /&gt;
&lt;br /&gt;
Алгоритм PAM &#039;&#039;конечен&#039;&#039;, так как:&lt;br /&gt;
* количество операций фазы BUILD конечно;&lt;br /&gt;
* значение целевой фукнции неотрицательно и на каждой итерации фазы SWAP строго уменьшается.&lt;br /&gt;
&lt;br /&gt;
Одно из преимуществ алгоритма PAM заключается в том, что он может работать с любой матрицей различий. В данном случае принципиальное отличие от матрицы расстояний заключается в том, что для матрицы различий может не выполняться неравенство треугольника, так как в основе её построения не обязательно используется метрика.&lt;br /&gt;
&lt;br /&gt;
Основные операция алгоритма PAM: сложение и нахождение минимума. Операция взятия минимума не подвержена процессу накопления ошибки. На каждой итерации алгоритма сложение производится над значениями, взятыми непосредственно из исходных данных. Таким образом, алгоритм PAM не накапливает ошибок в процессе своей работы и является &#039;&#039;устойчивым&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
При &amp;lt;math&amp;gt;k(n-k) \, \bmod \, p \neq 0&amp;lt;/math&amp;gt; отсутствует возможность равномерно распределить задачи рассчёта &amp;lt;math&amp;gt;\overline{b}&amp;lt;/math&amp;gt; между процессами. Кроме того, если &amp;lt;math&amp;gt;k \, \bmod \, p \neq 0&amp;lt;/math&amp;gt;, то после их распределения для некоторых процессов окажется необходимым вычислить несколько соседних значений &amp;lt;math&amp;gt;\overline{a}.&amp;lt;/math&amp;gt; Таким образом, &#039;&#039;равномерная&#039;&#039; загрузка процессов &#039;&#039;не всегда возможна&#039;&#039;. Помимо этого, агрегирование данных с целью вычисления глобального минимума приводит к простою незадействованных процессов.&lt;br /&gt;
&lt;br /&gt;
Как и большинство алгоритмов кластеризации, PAM может сходиться к некоторому &#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;
==== Возможная параллельная реализация алгоритма PAM ====&lt;br /&gt;
&lt;br /&gt;
Необходимость уменьшения времени решения задачи приводит к потребности в создании паралельной реализации алгоритма. В дальнейшем будем придерживаться следующих допущений:&lt;br /&gt;
* возможно использование &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; процессов;&lt;br /&gt;
* не нарушая общности суждений, множества &amp;lt;math&amp;gt;M, O&amp;lt;/math&amp;gt; - упорядоченны.&lt;br /&gt;
&lt;br /&gt;
Приведённые далее возможные схемы для параллельных реализаций фазы BUILD и фазы SWAP основаны на максимально равномерном распределении задач между процессами.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Возможная параллельная реализация фазы BUILD =====&lt;br /&gt;
&lt;br /&gt;
Главная задача заключается в распараллеливании многочисленных вычислений целевой функции на каждой итерации фазы BUILD:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;F^i = \min_{x_{o_h} \in O_{i-1}} F_{x_{o_h}}^i,&amp;lt;/math&amp;gt; где &amp;lt;math&amp;gt;F_{x_{o_h}}^i = \sum_{j = 1}^{n} \overline{MIN}_{i, x_{o_h}}^{(j)},&amp;lt;/math&amp;gt; где&lt;br /&gt;
: &amp;lt;math&amp;gt;\overline{MIN}_{1, x_{o_h} \in O_0} = \{ \rho (x_{o_h}, x_j ) \| 1 \leq j \leq n \};&amp;lt;/math&amp;gt;&lt;br /&gt;
: &amp;lt;math&amp;gt;\overline{MIN}_{i, x_{o_h} \in O_{i-1}} = \{ \min ( \overline{MIN}_{i-1, x_{m_{i-1}}}^{(j)}, \rho (x_{o_h}, x_j) ) \| 1 \leq j \leq n \}, \forall i: 1 &amp;lt; i \leq k.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Схема реализации&#039;&#039;: &amp;lt;br&amp;gt;(далее &amp;lt;math&amp;gt;0 &amp;lt; i \leq k &amp;lt;/math&amp;gt; - номер текущей итерации)&lt;br /&gt;
# для каждого процесса с номером &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(0 \leq j &amp;lt; p):&amp;lt;/math&amp;gt;&lt;br /&gt;
## положим:&lt;br /&gt;
##: &amp;lt;math&amp;gt;pos = p-(n-i+1) \, \bmod \, p;&amp;lt;/math&amp;gt;&lt;br /&gt;
## на каждой итерации процессу необходимо вычислить &amp;lt;math&amp;gt;r_j&amp;lt;/math&amp;gt; значений целевой функции для соответствующих ему элементов &amp;lt;math&amp;gt;x_{o_h}, ..., x_{o_{h+(r_j-1)}}:&amp;lt;/math&amp;gt;&lt;br /&gt;
##: &amp;lt;math&amp;gt; r_j = \begin{cases}&lt;br /&gt;
    \lfloor \frac{n-i+1}{p} \rfloor , 0 \leq j &amp;lt; pos &amp;amp; \quad\\&lt;br /&gt;
    \lceil \frac{n-i+1}{p} \rceil , pos  \leq j &amp;amp; \quad\\&lt;br /&gt;
  \end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
##: &amp;lt;math&amp;gt;h = \begin{cases}&lt;br /&gt;
    r_j*j , 0 \leq j &amp;lt; pos &amp;amp; \quad\\&lt;br /&gt;
    (r_j-1)*pos + (j-pos)*r_j , pos  \leq j &amp;amp; \quad\\&lt;br /&gt;
  \end{cases}&amp;lt;/math&amp;gt; - порядковый номер &amp;lt;math&amp;gt;x_{o_h};&amp;lt;/math&amp;gt;&lt;br /&gt;
#:&lt;br /&gt;
#:&lt;br /&gt;
# каждому процессу с номером &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(0 \leq j &amp;lt; p):&amp;lt;/math&amp;gt;&lt;br /&gt;
## найти минимум среди значений целевой функции &amp;lt;math&amp;gt;F_{x_{o_h}}^i&amp;lt;/math&amp;gt; для каждого из значений параметра &amp;lt;math&amp;gt;x_{o_h};&amp;lt;/math&amp;gt; &lt;br /&gt;
##* в данном случае может быть использована оптимизация, описанная в [[#Вычислительное ядро алгоритма|вычислительном ядре алгоритма]];&lt;br /&gt;
## для процессов с номером &amp;lt;math&amp;gt;j \neq 0&amp;lt;/math&amp;gt; переслать процессу с номером &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt; пару &amp;lt;math&amp;gt;(x_{o_h}, F_{x_{o_h}}^i)&amp;lt;/math&amp;gt; для всех обработанных &amp;lt;math&amp;gt;x_{o_h};&amp;lt;/math&amp;gt;&lt;br /&gt;
#:&lt;br /&gt;
#:&lt;br /&gt;
# для процесса с номером &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt;:&lt;br /&gt;
## принять пары от процессов &amp;lt;math&amp;gt;(0, p-1],&amp;lt;/math&amp;gt; в ответ на шаг 2.2;&lt;br /&gt;
## найти &amp;lt;math&amp;gt;x_{o_h},&amp;lt;/math&amp;gt; для которого целевая функция принимает минимальное значение, и положить &amp;lt;math&amp;gt;x_{m_i}:=x_{o_h};&amp;lt;/math&amp;gt;&lt;br /&gt;
## вычислить &amp;lt;math&amp;gt;\overline{MIN}_{i, x_{m_i}}&amp;lt;/math&amp;gt;;&lt;br /&gt;
## разослать пару &amp;lt;math&amp;gt;(x_{m_i}, \overline{MIN}_{i, x_{m_i}})&amp;lt;/math&amp;gt; при помощи широковещательной рассылки;&lt;br /&gt;
#:&lt;br /&gt;
#:&lt;br /&gt;
# для каждого процесса с номером &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(0 \leq j &amp;lt; p):&amp;lt;/math&amp;gt;&lt;br /&gt;
## принять пару &amp;lt;math&amp;gt;(x_{m_i}, \overline{MIN}_{i, x_{m_i}})&amp;lt;/math&amp;gt; в ответ на шаг 3.4;&lt;br /&gt;
## скорректировать локальные копии множеств &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt;, изменив принадлежность вектора &amp;lt;math&amp;gt;x_{m_i}&amp;lt;/math&amp;gt;, а также обновить хранимое значение вектора &amp;lt;math&amp;gt;\overline{MIN}&amp;lt;/math&amp;gt; для подготовки к следующей итерации;&lt;br /&gt;
## перейти к шагу 2.1.&lt;br /&gt;
#:&lt;br /&gt;
#:&lt;br /&gt;
После завершения &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; шагов фазы BUILD, множества &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; (одинаковые для каждого процесса согласно приведенной схеме), а так же значение целевой функции являются выходными данными фазы BUILD.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Возможная параллельная реализация фазы SWAP =====&lt;br /&gt;
&lt;br /&gt;
Главная задача заключается в распараллеливании многократного вычисления целевой функции на каждой итерации фазы SWAP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;F^i = \min_{x_{m_s} \in M_{i-1} } \min_{x_{o_h} \in O_{i-1}} \sum_{j = 1}^{n} \min ( \min_{ x_{m_l} \in M_{i-1} \backslash \{x_{m_s}\} } ( \rho ( x_{m_l},x_j )) , \rho ( x_{o_h},x_j) )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Схема реализации&#039;&#039;: &amp;lt;br&amp;gt;(далее &amp;lt;math&amp;gt;i \in \N&amp;lt;/math&amp;gt; - номер текущей итерации)&lt;br /&gt;
# для каждого процесса с номером &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(0 \leq j &amp;lt; p):&amp;lt;/math&amp;gt;&lt;br /&gt;
## положим:&lt;br /&gt;
##: &amp;lt;math&amp;gt;pos = p-(k*(n-k)) \, \bmod \, p;&amp;lt;/math&amp;gt;&lt;br /&gt;
## на каждой итерации процессу необходимо вычислить &amp;lt;math&amp;gt;r_j&amp;lt;/math&amp;gt; значений целевой функции для соответствующих ему пар вида (медоид, не-медоид)   &amp;lt;math&amp;gt;(x_{m_s}, x_{o_h}), (x_{m_s}, x_{o_{h+1}}), ..., (x_{m_s}, x_{o_{n-k}}), (x_{m_{s+1}}, x_{o_0}), (x_{m_{s+1}}, x_{o_1}), . . . \, : &amp;lt;/math&amp;gt;&lt;br /&gt;
##:&amp;lt;math&amp;gt; r_j =   \begin{cases}&lt;br /&gt;
    \lfloor \frac{k*(n-k)}{p} \rfloor , 0 \leq j &amp;lt; pos &amp;amp; \quad\\&lt;br /&gt;
    \lceil \frac{k*(n-k)}{p} \rceil , pos  \leq j &amp;amp; \quad\\&lt;br /&gt;
  \end{cases}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
##: &amp;lt;math&amp;gt;s = \begin{cases}&lt;br /&gt;
    (r_j*j) \mbox{ div } (n-k) , 0 \leq j &amp;lt; pos &amp;amp; \quad\\&lt;br /&gt;
     ((r_j-1)*pos + r_j*(j-pos)) \mbox{ div } (n-k), pos  \leq j &amp;amp; \quad\\&lt;br /&gt;
  \end{cases}&amp;lt;/math&amp;gt; - порядковый номер &amp;lt;math&amp;gt;x_{m_s};&amp;lt;/math&amp;gt;&lt;br /&gt;
##: &amp;lt;math&amp;gt;h = \begin{cases}&lt;br /&gt;
    (r_j*j) \, \bmod \,  (n-k) , 0 \leq j &amp;lt; pos &amp;amp; \quad\\&lt;br /&gt;
     ((r_j-1)*pos + r_j*(j-pos)) \, \bmod \,  (n-k), pos  \leq j &amp;amp; \quad\\&lt;br /&gt;
  \end{cases}&amp;lt;/math&amp;gt; - порядковый номер &amp;lt;math&amp;gt;x_{o_h};&amp;lt;/math&amp;gt;&lt;br /&gt;
#:&lt;br /&gt;
#:&lt;br /&gt;
# каждому процессу с номером &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(0 \leq j &amp;lt; p):&amp;lt;/math&amp;gt;&lt;br /&gt;
## найти минимум среди вычисленных значений целевой функции для каждого из значений первого параметра &amp;lt;math&amp;gt;x_{m_s}&amp;lt;/math&amp;gt; по соответствующим ему &amp;lt;math&amp;gt;x_{o_h};&amp;lt;/math&amp;gt;&lt;br /&gt;
##* в данном случае может быть использована оптимизация, описанная в [[#Вычислительное ядро алгоритма|вычислительном ядре алгоритма]];&lt;br /&gt;
## переслать процессу с номером &amp;lt;math&amp;gt;N = s \, \bmod \, p&amp;lt;/math&amp;gt; (если &amp;lt;math&amp;gt;N \neq j&amp;lt;/math&amp;gt;) тройку &amp;lt;math&amp;gt;(F_{x_{m_s}, x_{o_h}}^{i_j}, x_{m_s}, x_{o_h})&amp;lt;/math&amp;gt; для всех обработанных &amp;lt;math&amp;gt;x_{m_s};&amp;lt;/math&amp;gt;&lt;br /&gt;
# для процессов с номерами &amp;lt;math&amp;gt;j&amp;lt;\min (p, k):&amp;lt;/math&amp;gt;&lt;br /&gt;
## принять описанные выше тройки от процессов, обработавших элементы &amp;lt;math&amp;gt;x_{m_{z \, \bmod \, p = j}}, z = \overline {0, k-1},&amp;lt;/math&amp;gt; в ответ на шаг 2.2;&lt;br /&gt;
## вычислить минимальное среди полученных значений целевой функции;&lt;br /&gt;
## запомнить &amp;lt;math&amp;gt;x_{m_s}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;x_{o_h}&amp;lt;/math&amp;gt;, на которых минимальное значение было достигнуто;&lt;br /&gt;
## при &amp;lt;math&amp;gt;j \neq 0 &amp;lt;/math&amp;gt; отправить тройку &amp;lt;math&amp;gt;(F_{x_{m_s}, x_{o_h}}^{i_j}, x_{m_s}, x_{o_h})&amp;lt;/math&amp;gt;, соответствующую выбранной паре, процессу с номером &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt;;&lt;br /&gt;
# для процесса с номером &amp;lt;math&amp;gt;0&amp;lt;/math&amp;gt;:&lt;br /&gt;
## принять тройки от процессов &amp;lt;math&amp;gt;(0, min(k-1, p-1)],&amp;lt;/math&amp;gt; в ответ на шаг 3.4;&lt;br /&gt;
## найти пару &amp;lt;math&amp;gt;(x_{m_s}, x_{o_h})&amp;lt;/math&amp;gt;, для которой целевая функция принимает минимальное значение;&lt;br /&gt;
## сравнить найденное минимальное значение с вычисленным значением целевой функции на предыдущей итерации фазы SWAP;&lt;br /&gt;
### (&#039;&#039; &#039;&#039;&#039;условие останова&#039;&#039;&#039; &#039;&#039;) если значение целевой функции не уменьшилось, остановить вычисление;&lt;br /&gt;
### иначе, разослать выявленную пару &amp;lt;math&amp;gt;(x_{m_s}, x_{o_h})&amp;lt;/math&amp;gt; при помощи широковещательной рассылки;&lt;br /&gt;
# для каждого процесса с номером &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt; &amp;lt;math&amp;gt;(0 \leq j &amp;lt; p):&amp;lt;/math&amp;gt;&lt;br /&gt;
## принять пару &amp;lt;math&amp;gt;(x_{m_s}, x_{o_h})&amp;lt;/math&amp;gt; в ответ на шаг 4.3.2;&lt;br /&gt;
## скорректировать локальные копии множеств &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt;, заменяя элемент &amp;lt;math&amp;gt;x_{m_s}&amp;lt;/math&amp;gt; на элемент &amp;lt;math&amp;gt;x_{o_h}&amp;lt;/math&amp;gt; и наоборот;&lt;br /&gt;
## перейти к шагу 2.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Ограничения и недостатки =====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ограничения&#039;&#039;:&lt;br /&gt;
* предполагается, что матрица расстояний &amp;lt;math&amp;gt;D^{n * n}&amp;lt;/math&amp;gt; полностью помещается в памяти каждого процесса.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Недостатки&#039;&#039;:&lt;br /&gt;
* при распределении обсчитываемых целевых функций, каждому из процессов ставится в соответствие некоторая совокупность пар &amp;lt;math&amp;gt;(x_{m_s}, x_{o_h})&amp;lt;/math&amp;gt;, для которых нужно рассчитать значения целевой функции. В случае, если количество процессов не кратно количеству обрабатываемых кластеров, различные процессы получат пары у которых совпадают &amp;lt;math&amp;gt;x_{m_s}&amp;lt;/math&amp;gt;, что приведёт к совершению одинаковых вычислений на различных процессах: &amp;lt;math&amp;gt;   \min_{ x_{m_l} \in M_{i-1} \backslash \{x_{m_s}\} } ( \rho ( x_{m_l},x_j )), 1 \leq j \leq n;&amp;lt;/math&amp;gt;&lt;br /&gt;
* вычисление фазы SWAP успешно распараллеливается между &amp;lt;math&amp;gt;p&amp;lt;/math&amp;gt; процессами, однако после этого происходит агрегация данных в 2 этапа относительно &amp;lt;math&amp;gt;(x_{m_s}, x_{o_h})&amp;lt;/math&amp;gt; для вычисления глобального минимума. На первом этапе данные собираются на первых &amp;lt;math&amp;gt;\min (p,k)&amp;lt;/math&amp;gt; процессах, где происходят локальные вычисления минимумов среди принятых данных (для каждого &amp;lt;math&amp;gt;x_{m_s}&amp;lt;/math&amp;gt;), после чего полученные минимумы и связанная с ними информация агрегируются на мастер-процессе, который вычисляет глобальный минимум и извещает о нём все остальные процессы. &amp;lt;br&amp;gt;Во время описанных вычислений все незадействованные процессы простаивают.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Дополнительные возможности&#039;&#039;:&lt;br /&gt;
* помимо описанной схемы, также есть возможность распараллелить операцию вычисления матрицы расстояний &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, однако это является отдельной алгоритмической задачей и не даёт существенного прироста производительности алгоритма.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Существующие параллельные реализации алгоритма PAM ====&lt;br /&gt;
&lt;br /&gt;
Примером другой параллельной реализации алгоритма PAM может служить реализация в пакете SPRINT для языка R (подробнее см. [[#Существующие реализации алгоритма|существующие реализации алгоритма]]).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
&lt;br /&gt;
Структура графа алгоритма (см. 1.7 [[#Информационный граф| Информационный граф алгоритма]]) такова, что позволяет надеяться на получение хорошей масштабируемости.&lt;br /&gt;
&lt;br /&gt;
Исследование масштабируемости параллельной реализации алгоритма Partitioning Around Medoids проводилось на суперкомпьютере BlueGene/P &amp;lt;ref&amp;gt;IBM BlueGene/P  - [http://hpc.cmc.msu.ru http://hpc.cmc.msu.ru]&amp;lt;/ref&amp;gt;.&lt;br /&gt;
Отметим, что для данному суперкомпьютеру свойственна стабильность по времени вычисления одной и той же задачи при различных запусках.&lt;br /&gt;
Во время вычислений каждому MPI процессу соответствовало 1 ядро процессора PowerPC 450, 850 MHz с пиковой производительностью 3.4 GFlop/sec per core.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Набор и границы значений изменяемых [[Глоссарий#Параметры запуска|параметров запуска]] реализации алгоритма:&lt;br /&gt;
* число процессов (p):&lt;br /&gt;
** [1; 4 : 512] с шагом 4 процесса;&lt;br /&gt;
* размер кластеризуемого множества (n):&lt;br /&gt;
** [4; 16; 32; 64];&lt;br /&gt;
** [128 : 3200] с шагом 128 элементов;&lt;br /&gt;
* каждому размеру кластеризуемого множества соответствует количество кластеров для разбиения (k):&lt;br /&gt;
** [2; 4; 4; 8];&lt;br /&gt;
** [2 : 50] с шагом 2.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Особенности проведения эксперимента:&lt;br /&gt;
* тестовые данные являются псевдослучайными;&lt;br /&gt;
* для всех экспериментов использовался одинаковый набор данных;&lt;br /&gt;
* в соответствии с описанными параметрами запуска, для множеств размерности [128 : 3200], количество кластеров (k) прямо пропорционально размеру задачи (n).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В результате проведённых экспериментов был получен широкий диапазон [[Глоссарий#Эффективность распараллеливания|эффективности реализации]] алгоритма:&lt;br /&gt;
* минимальная эффективность реализации: &amp;lt;math&amp;gt;3.4 * 10^{-9} \, %&amp;lt;/math&amp;gt; достигается при использовании 512 процессов для множества из 4 элементов и 2-х кластеров (результат вызван избыточностью количества процессов по отношению к размеру задачи);&lt;br /&gt;
* максимальная эффективность реализации: &amp;lt;math&amp;gt;4.1 * 10^{-4} \, %&amp;lt;/math&amp;gt; достигается при использовании 4 процессов для множества из 128 элементов и 2 кластеров.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Абсолютная величина [[Глоссарий#Производительность|производительности алгоритма]] (GFlops) определялась как количество операций с плавающей точкой за секунду. Точное количество операций было вычислено на основании [[#Последовательная сложность алгоритма| последовательной сложности алгоритма]], целочисленные операции и операции работы с памятью не учитывались.&lt;br /&gt;
&lt;br /&gt;
Таким образом, производительность обусловлена как самим алгоритмом (его внутренняя структура определяет соотношение между операциями работы с памятью, операциями над целочисленными значениями и значениями с плавающей точкой), так и используемой реализацией.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
На следующих рисунках приведены графики производительности и эффективности выбранной реализации PAM в зависимости от изменяемых параметров запуска:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{|style=&amp;quot;margin: 0 auto;&amp;quot;&lt;br /&gt;
 | [[file:PAM-gflops.png|thumb|none|600px|Рисунок 5а. Параллельная реализация алгоритма PAM. Изменение производительности в зависимости от числа процессов и размера множества.]]&lt;br /&gt;
 | [[file:PAM-gflops-top-view.png|thumb|none|600px|Рисунок 5б. Параллельная реализация алгоритма PAM. Изменение производительности в зависимости от числа процессов и размера множества. Вид сверху.]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
[[file:PAM-gflops.png|thumb|center|800px|Рисунок 5а. Параллельная реализация алгоритма PAM. Изменение производительности в зависимости от числа процессов и размера множества.]]&lt;br /&gt;
[[file:PAM-gflops-top-view.png|thumb|center|800px|Рисунок 5б. Параллельная реализация алгоритма PAM. Изменение производительности в зависимости от числа процессов и размера множества. Вид сверху.]]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
[[file:PAM-efficiency.png|thumb|center|800px|Рисунок 6. Параллельная реализация алгоритма PAM. Изменение эффективности в зависимости от числа процессов и размера множества.]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
На рисунке 5б, видно, что пики организованы в прямые. Это обусловлено инвариантностью величины &amp;lt;math&amp;gt;a&amp;lt;/math&amp;gt; в соответствии с описанной в [[#Вычислительное ядро алгоритма | вычислительном ядре фазы SWAP]] оптимизацией. На рисунке 3 для [[#Информационный граф фазы SWAP| информационного графа фазы SWAP]] наглядно видно, что при построчном распределении вычислений &amp;lt;math&amp;gt;\overline{b}_{x_{m_s, o_h}}&amp;lt;/math&amp;gt; возможно возникновение следующих ситуаций (далее при &#039;&#039; &#039;&#039;&#039;k * (n-k) mod p == 0&#039;&#039;&#039; &#039;&#039; обозначим &#039;&#039; &#039;&#039;&#039;r = k * (n-k) / p&#039;&#039;&#039; &#039;&#039;):&lt;br /&gt;
# при &#039;&#039; &#039;&#039;&#039;r &amp;lt; (n-k)&#039;&#039;&#039; &#039;&#039;, если &#039;&#039; &#039;&#039;&#039;(n-k) mod r == 0&#039;&#039;&#039; &#039;&#039;, то каждому процессу необходимо вычислить ровно одну величину &amp;lt;math&amp;gt;\overline{a}_{x_{m_s}};&amp;lt;/math&amp;gt;&lt;br /&gt;
# при &#039;&#039; &#039;&#039;&#039;r &amp;amp;ge; (n-k)&#039;&#039;&#039; &#039;&#039;, если &#039;&#039; &#039;&#039;&#039;k mod p == 0&#039;&#039;&#039; &#039;&#039;, то каждому процессу необходимо вычислить несколько соответствующих ему величин &amp;lt;math&amp;gt;\overline{a}_{x_{m_s}},&amp;lt;/math&amp;gt; при этом каждая величина будет вычислена ровно в одном процессе;&lt;br /&gt;
# в остальных случаях вычисления величин &amp;lt;math&amp;gt;\overline{b}_{x_{m_s, o_h}}&amp;lt;/math&amp;gt; распределяются между процессами таким образом, что часть процессов обрабатывает больше величин &amp;lt;math&amp;gt;\overline{a}_{x_{m_s}}&amp;lt;/math&amp;gt; нежели остальные (ситуация возникает при обработке процессом последних элементов одной строки и первых элементов следующей). Подобная ситуация приводит к дополнительным вычислениям на некоторых процессах и, как следствие, к простою остальных, в связи с чем происходит падение производительности.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Первые два случая приводят к равномерному распределению нагрузки между процессами, и им соответствуют видимые пики на приведённых рисунках 5a, 5б, 6. Для 3-го случая из-за неравномерной загрузки процессов достигаемая производительность падает.&lt;br /&gt;
&lt;br /&gt;
Второй случай соответствует размеру задачи меньшему, чем количество процессов и на практике маловероятен.&lt;br /&gt;
Таким образом, для повышения производительности следует выбирать количество процессов так, чтобы &#039;&#039; &#039;&#039;&#039;k * (n-k)&#039;&#039;&#039; &#039;&#039; и &#039;&#039; &#039;&#039;&#039;(n-k)&#039;&#039;&#039; &#039;&#039; были кратны &#039;&#039; &#039;&#039;&#039;p&#039;&#039;&#039; &#039;&#039; и &#039;&#039; &#039;&#039;&#039;k * (n-k) div p&#039;&#039;&#039; &#039;&#039; соответственно.&lt;br /&gt;
&lt;br /&gt;
Для исследуемой реализации, вычисление величин &amp;lt;math&amp;gt;\overline{a}_{x_{m_s}}&amp;lt;/math&amp;gt; может быть оптимизировано (за счёт распределения между процессами и последующих пересылок). Однако принципиальный вид графиков останется тем же: пики будут наблюдаться для случаев равномерного распределения вычислительных задач между процессами.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Построим оценки масштабируемости выбранной реализации алгоритма PAM:&lt;br /&gt;
* По числу процессов: &amp;lt;math&amp;gt;- \, 1.6 * 10^{-8}.&amp;lt;/math&amp;gt; С ростом числа процессов эффективность на рассмотренной области изменений параметров запуска уменьшается. Этот результат вызван ростом времени, затрачиваемого на пересылку данных, то есть ростом накладных расходов на организацию параллельного выполнения.&lt;br /&gt;
* По размеру задачи: &amp;lt;math&amp;gt;3.9 * 10^{-7}&amp;lt;/math&amp;gt;. С ростом размера задачи эффективность на рассмотренной области изменений параметров запуска увеличивается. Этот результат вызван увеличением количества вычислений относительно объема пересылок данных.&lt;br /&gt;
* Общая оценка масштабируемости: &amp;lt;math&amp;gt;- \, 1.2 * 10^{-9}&amp;lt;/math&amp;gt;. При рассмотрении области параметров запуска в целом можно говорить о том, что с ростом размера задачи и числа процессов эффективность незначительно падает.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[https://github.com/phonexicum/pam-mpi-cmc Исследованная параллельная реализация на языке C++] (реализация написана самостоятельно)&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
# Последовательная реализация алгоритма PAM в пакете ClusterR на языке R:&lt;br /&gt;
#* Лицензия: MIT&lt;br /&gt;
#* [https://cran.r-project.org/package=ClusterR веб-страница фреймворка (исходный код, системные требования и справочное руководство)]&lt;br /&gt;
#* Алгоритм PAM реализован в функции &#039;Cluster_Medoids&#039;. Отличительная особенность реализации &amp;lt;ref&amp;gt;Lampros Mouselimis [https://cran.r-project.org/web/packages/cluster/cluster.pdf Package &#039;ClusterR&#039;]. October 8, 2016&amp;lt;/ref&amp;gt;:&lt;br /&gt;
#** для задания метрики между элементами кластеризуемого множества передаётся строка, задающая одну из реализованных в алгоритме метрик. Данный подход теряет одно из преимуществ алгоритма PAM, позволяющее в качестве матрицы расстояний использовать произвольную матрицу различий.&lt;br /&gt;
#:&lt;br /&gt;
#:&lt;br /&gt;
# Последовательная реализация алгоритма PAM в пакете Cluster на языке R:&lt;br /&gt;
#* Лицензия: GPL (≥2)&lt;br /&gt;
#* [https://cran.r-project.org/package=cluster веб-страница фреймворка (исходный код, системные требования и справочное руководство)]&lt;br /&gt;
#* Алгоритм PAM реализован в функции &#039;pam()&#039;. Данная реализация имеет следующие особенности &amp;lt;ref&amp;gt;Martin Maechler., etc. [https://cran.r-project.org/web/packages/cluster/cluster.pdf Package &#039;cluster&#039;]. October 8, 2016&amp;lt;/ref&amp;gt;:&lt;br /&gt;
#** функция может принимать на вход не множество точек, а матрицу расстояний между ними;&lt;br /&gt;
#** реализация более гибкая, так как принимает на вход матрицу различий элементов, а не использует какую-либо метрику;&lt;br /&gt;
#** может быть предоставлено графическое отображение.&lt;br /&gt;
#:&lt;br /&gt;
#:&lt;br /&gt;
#:&lt;br /&gt;
# Параллельная реализация алгоритма PAM в пакете SPRINT (Simple Parallel R INTerface - параллельный фреймворк) на языке R:&lt;br /&gt;
#* Лицензия: GPL (≥3)&lt;br /&gt;
#* [https://cran.r-project.org/package=sprint веб-страница фреймворка (исходный код, системные требования и справочное руководство)]&lt;br /&gt;
#* Алгоритм PAM реализован в фукции &#039;ppam()&#039;. Входные параметры данной функции схожи с параметрами, задаваемыми в линейной реализации &#039;pam()&#039; пакета Cluster языка R. Отличительной особенностью является подача на вход предвычисленной матрицы расстояний (например, с помощью функции &#039;pcor()&#039; из этой же библиотеки).&amp;lt;ref&amp;gt;University of Edinburgh SPRINT Team. [https://cran.r-project.org/web/packages/sprint/sprint.pdf Package &#039;sprint&#039;]. February 20, 2015&amp;lt;/ref&amp;gt;&lt;br /&gt;
#:&lt;br /&gt;
#:&lt;br /&gt;
# Параллельная реализация алгоритма PAM на основе операций MapReduce на Hadoop кластере.&lt;br /&gt;
#* В рамках исследования по ускорению анализа информации о геноме были созданы реализации алгоритма PAM с использованием технологии MPI и технологии MapReduce. Реализация в открытом досупе отсутствует. &amp;lt;ref&amp;gt;Dobrzelecki B. et al. Managing and analysing Genomic Data using HPC and Clouds //Grid and Cloud Database Management. – Springer Berlin Heidelberg, 2011. – С. 261-277.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
MKL, ScaLAPACK, PETSc, FFTW, ATLAS, Magma и другие подобные библиотеки.&lt;br /&gt;
&lt;br /&gt;
* Дать ссылки на существующие последовательные и параллельные реализации алгоритма (&amp;quot;уже доступные&amp;quot;)&lt;br /&gt;
* Реализация - коммерческая/свободная, лицензия&lt;br /&gt;
* ссылка на дистрибутив и описание&lt;br /&gt;
* особенности, достоинства/недостатки, ....&lt;br /&gt;
&lt;br /&gt;
гугл-запрос: &amp;quot;partitioning around medoids&amp;quot; &amp;quot;PAM&amp;quot; BUILD SWAP &amp;quot;MPI&amp;quot; &amp;quot;program&amp;quot; &amp;quot;package&amp;quot; -worldwidescience&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Литература ==&lt;/div&gt;</summary>
		<author><name>Dexter</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%A0%D1%83%D1%81%D0%BB%D0%B0%D0%BD/%D0%9F%D0%BB%D0%BE%D1%82%D0%BD%D0%BE%D1%81%D1%82%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&amp;diff=18918</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%A0%D1%83%D1%81%D0%BB%D0%B0%D0%BD/%D0%9F%D0%BB%D0%BE%D1%82%D0%BD%D0%BE%D1%81%D1%82%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&amp;diff=18918"/>
		<updated>2016-11-22T08:22:08Z</updated>

		<summary type="html">&lt;p&gt;Dexter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;1) В тексте нет ни одной ссылки на источники из списка литературы&lt;br /&gt;
&lt;br /&gt;
2) Поясните, что значит &amp;quot;плотно-достижимые&amp;quot;&lt;/div&gt;</summary>
		<author><name>Dexter</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:Igor.orpanen&amp;diff=18917</id>
		<title>Обсуждение участника:Igor.orpanen</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:Igor.orpanen&amp;diff=18917"/>
		<updated>2016-11-22T08:14:41Z</updated>

		<summary type="html">&lt;p&gt;Dexter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&#039;&#039;&#039;Еще замечания&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
1) Проверьте грамматику и орфографию. Нашел, например, &amp;quot;максимальное расстояния&amp;quot; &lt;br /&gt;
&lt;br /&gt;
2) Пункт 1.3 - &amp;quot;используется предварительные расчёты&amp;quot;. Какие расчеты?&lt;br /&gt;
&lt;br /&gt;
3) Поясните, что такое  &amp;quot;k-d tree, r-tree и vantage-point tree&amp;quot;, упомянутые несколько раз&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Замечания к оформлению статьи:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
0. Если рисунок не ваш, то требуется указать ссылку на ресурс, откуда он был взят.&lt;br /&gt;
&lt;br /&gt;
1. В пункте 1.3 расшифруйте фразу: &amp;quot;построение специальных структур данных&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
3. Пункт 1.5 стоит подписать комментарии к блоку псевдокода.&lt;br /&gt;
&lt;br /&gt;
4. В пункте 1.7 написать пояснение к информационным графам и сделать их более подробными (особенно требуется расписать более подробно оранжевые блоки).&lt;br /&gt;
&lt;br /&gt;
5. Вычислительная мощность не приведена. (см. пример: https://algowiki-project.org/ru/%D0%A0%D0%B0%D0%B7%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5_%D0%A5%D0%BE%D0%BB%D0%B5%D1%86%D0%BA%D0%BE%D0%B3%D0%BE_(%D0%BC%D0%B5%D1%82%D0%BE%D0%B4_%D0%BA%D0%B2%D0%B0%D0%B4%D1%80%D0%B0%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%BA%D0%BE%D1%80%D0%BD%D1%8F)&lt;/div&gt;</summary>
		<author><name>Dexter</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:Igor.orpanen&amp;diff=18916</id>
		<title>Обсуждение участника:Igor.orpanen</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:Igor.orpanen&amp;diff=18916"/>
		<updated>2016-11-22T08:14:09Z</updated>

		<summary type="html">&lt;p&gt;Dexter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&#039;&#039;&#039;Еще замечания&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
1) Проверьте грамматику и орфографию. Нашел, например, &amp;quot;максимальное расстояния&amp;quot; &lt;br /&gt;
&lt;br /&gt;
2) Пункт 1.3 - &amp;quot;используется предварительные расчёты&amp;quot;. Какие расчеты?&lt;br /&gt;
&lt;br /&gt;
3) Поясните, что такое  &amp;quot;k-d tree, r-tree и vantage-point tree&amp;quot;, упомянутые несколько раз&lt;br /&gt;
&lt;br /&gt;
Замечания к оформлению статьи:&lt;br /&gt;
&lt;br /&gt;
0. Если рисунок не ваш, то требуется указать ссылку на ресурс, откуда он был взят.&lt;br /&gt;
&lt;br /&gt;
1. В пункте 1.3 расшифруйте фразу: &amp;quot;построение специальных структур данных&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
3. Пункт 1.5 стоит подписать комментарии к блоку псевдокода.&lt;br /&gt;
&lt;br /&gt;
4. В пункте 1.7 написать пояснение к информационным графам и сделать их более подробными (особенно требуется расписать более подробно оранжевые блоки).&lt;br /&gt;
&lt;br /&gt;
5. Вычислительная мощность не приведена. (см. пример: https://algowiki-project.org/ru/%D0%A0%D0%B0%D0%B7%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5_%D0%A5%D0%BE%D0%BB%D0%B5%D1%86%D0%BA%D0%BE%D0%B3%D0%BE_(%D0%BC%D0%B5%D1%82%D0%BE%D0%B4_%D0%BA%D0%B2%D0%B0%D0%B4%D1%80%D0%B0%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%BA%D0%BE%D1%80%D0%BD%D1%8F)&lt;/div&gt;</summary>
		<author><name>Dexter</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:Igor.orpanen&amp;diff=18915</id>
		<title>Обсуждение участника:Igor.orpanen</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:Igor.orpanen&amp;diff=18915"/>
		<updated>2016-11-22T08:13:29Z</updated>

		<summary type="html">&lt;p&gt;Dexter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Еще замечания&lt;br /&gt;
1) Проверьте грамматику и орфографию. Нашел, например, &amp;quot;максимальное расстояния&amp;quot; &lt;br /&gt;
&lt;br /&gt;
2) Пункт 1.3 - &amp;quot;используется предварительные расчёты&amp;quot;. Какие расчеты?&lt;br /&gt;
&lt;br /&gt;
3) Поясните, что такое  &amp;quot;k-d tree, r-tree и vantage-point tree&amp;quot;, упомянутые несколько раз&lt;br /&gt;
&lt;br /&gt;
Замечания к оформлению статьи:&lt;br /&gt;
&lt;br /&gt;
0. Если рисунок не ваш, то требуется указать ссылку на ресурс, откуда он был взят.&lt;br /&gt;
&lt;br /&gt;
1. В пункте 1.3 расшифруйте фразу: &amp;quot;построение специальных структур данных&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
3. Пункт 1.5 стоит подписать комментарии к блоку псевдокода.&lt;br /&gt;
&lt;br /&gt;
4. В пункте 1.7 написать пояснение к информационным графам и сделать их более подробными (особенно требуется расписать более подробно оранжевые блоки).&lt;br /&gt;
&lt;br /&gt;
5. Вычислительная мощность не приведена. (см. пример: https://algowiki-project.org/ru/%D0%A0%D0%B0%D0%B7%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5_%D0%A5%D0%BE%D0%BB%D0%B5%D1%86%D0%BA%D0%BE%D0%B3%D0%BE_(%D0%BC%D0%B5%D1%82%D0%BE%D0%B4_%D0%BA%D0%B2%D0%B0%D0%B4%D1%80%D0%B0%D1%82%D0%BD%D0%BE%D0%B3%D0%BE_%D0%BA%D0%BE%D1%80%D0%BD%D1%8F)&lt;/div&gt;</summary>
		<author><name>Dexter</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%BD%D1%82%D0%BE%D0%BD_%D0%A2%D0%BE%D0%B4%D1%83%D0%B0/Partitioning_Around_Medoids_(PAM)&amp;diff=18167</id>
		<title>Участник:Антон Тодуа/Partitioning Around Medoids (PAM)</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%BD%D1%82%D0%BE%D0%BD_%D0%A2%D0%BE%D0%B4%D1%83%D0%B0/Partitioning_Around_Medoids_(PAM)&amp;diff=18167"/>
		<updated>2016-11-18T14:51:25Z</updated>

		<summary type="html">&lt;p&gt;Dexter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Преподаватель 1|Dexter}} &lt;br /&gt;
{{Assignment|Zhum}}&lt;br /&gt;
&lt;br /&gt;
{{algorithm&lt;br /&gt;
| name              = Partitioning Around Medoids&lt;br /&gt;
| serial_complexity = &amp;lt;math&amp;gt;O(Q * K * N^2)&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;K&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(Q * K * N)&amp;lt;/math&amp;gt;&lt;br /&gt;
| pf_width          = &amp;lt;math&amp;gt;O(K * (N - K))&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;
* [[Участник:Гусева_Юлия | Гусева Ю.В.]] (описание алгоритма)&lt;br /&gt;
Вклад авторов следует считать равноценным.&lt;br /&gt;
&lt;br /&gt;
== Свойства и структура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Алгоритм &#039;&#039;PAM&#039;&#039; (Partitioning Around Medoids) был предложен Чарли Кауфаманом (Charlie Kaufman) и Питером Русивом (Peter Rousseeuw) в 1987&amp;lt;ref&amp;gt;Kaufman, L. and P.J. Rousseeuw, Clustering by means of medoids, in: Y. Dodge (Ed.), Statistical Data Analysis based on the L1 Norm (North-Holland, Amsterdam, 1987) 405 — 416.&amp;lt;/ref&amp;gt;. Алгоритм является одним из распространённых вариантов реализации &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt;-medoids.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;PAM&#039;&#039; используется для выполнения кластеризации[https://en.wikipedia.org/wiki/Hierarchical_clustering] объектов — процесса автоматического разбиения некоторого множества объектов на кластеры (множества) на основе их схожести (наиболее схожие объекты, как правило, располагаются в одном кластере). В качестве исходных данных алгоритму необходима симметрическая матрица с нолями на главной диагонали (dissimilarity matrix), задающая расстояние (в смысле похожести) между объектами, для которых выполняется кластеризация и число кластеров, по которым следует распределить объекты. Стоит отметить, что не все алгоритмы кластеризации требует задания количества кластеров, например, методы иерархической[https://en.wikipedia.org/wiki/Hierarchical_clustering] кластеризации свободны от данного ограничения.&lt;br /&gt;
&lt;br /&gt;
Алгоритм &#039;&#039;PAM&#039;&#039; для каждого кластера в качестве его характерного представителя выбирает наиболее подходящий из объектов кластеризации. Выбранные объекты называются медоидами (medoids). Алгоритм состоит из двух стадий. Первая стадия – &#039;&#039;BUILD&#039;&#039; предназначена для выбора исходного множества медоидов. Вторая стадия – &#039;&#039;SWAP&#039;&#039; является итерационной. На каждой итерации стадии &#039;&#039;SWAP&#039;&#039; алгоритм пытается улучшить выбранное множество медоидов с помощью выполнения операции &#039;&#039;обмена&#039;&#039;, которая представляет собой замену одного медоида на один из объектов кластеризации. Алгоритм завершает свою работу, когда ни один из возможных обменов не позволяет улучшить разбиение на кластеры. Часто на практике, условием завершения работы алгоритма также является момент, когда наилучшее возможное улучшение кластеризации меньше заранее выбранной пороговой величины. Введение данной величины позволяет сократить число итераций. Последнее, однако, снижает качество кластеризации (иногда незначительно).&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
&lt;br /&gt;
В качестве исходных данных алгоритм принимает:&lt;br /&gt;
* Симметрическую матрицу &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; порядка &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; с нолями на главной диагонали для &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; объектов кластеризации: &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-я строка матрицы &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; определяет расстояние от &amp;lt;math&amp;gt;i&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; N&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для заданных входных данных, алгоритм выбирает &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; объектов - медоидов (medoids) из &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; объектов кластеризации. Все медоиды относится к разных кластерам и являются их характерными представителями. Кластеры остальных объектов (не медоидов) совпадают с кластером ближайшего к ним медоида. Ближайший к &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-му объекту медоид будем коротко назвать медоидом &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го объекта. Выбор медоидов осуществляется исходя из минимизации среднего расстояния (average dissimilarity) между объектами внутри одного кластера. От минимизации среднего расстояния можно перейти к минимизации суммы расстояний от объектов до их медоидов. Такой переход не повлияет на выбор медоидов, но позволит не накапливать ошибки округления, возникающие в результате операции деления. Стоит отметить, что в общем случае расстояние между объектами следует понимать как меру похожести (similarity) объектов.&lt;br /&gt;
&lt;br /&gt;
Для дальнейшего описания алгоритма введём следующие обозначения:&lt;br /&gt;
* &amp;lt;math&amp;gt;U&amp;lt;/math&amp;gt; – множество объектов кластеризации, не выбранных в качестве медоидов&lt;br /&gt;
* &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; – множество объектов кластеризации, выбранных в качестве медоидов&lt;br /&gt;
* &amp;lt;math&amp;gt;C_{ij}&amp;lt;/math&amp;gt; – изменение расстояния от &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-го объекта до его медоида в результате выбора &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го объекта в качестве медоида&lt;br /&gt;
* &amp;lt;math&amp;gt;T_{ijh}&amp;lt;/math&amp;gt; – изменение расстояния от &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-го объекта до его медоида, в результате &#039;&#039;обмена&#039;&#039; &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го медоида на &amp;lt;math&amp;gt;h&amp;lt;/math&amp;gt;-й объект&lt;br /&gt;
&lt;br /&gt;
Под &#039;&#039;обменом&#039;&#039; &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го медоида на &amp;lt;math&amp;gt;h&amp;lt;/math&amp;gt;-й объект будем понимать операцию, в результате которой &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-й медоид перестаёт быть медоидом, а &amp;lt;math&amp;gt;h&amp;lt;/math&amp;gt;-й объект выбирается в качестве медоида:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
S &amp;amp; = S - \{i\} + \{h\} \\&lt;br /&gt;
U &amp;amp; = U - \{h\} + \{i\}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Перед выполнением алгоритма множество &amp;lt;math&amp;gt;U&amp;lt;/math&amp;gt;содержит все объекты кластеризации, а множество &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; – пусто. Описание значений &amp;lt;math&amp;gt;C_{ij}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;T_{ijh}&amp;lt;/math&amp;gt; и способа их вычисления будет дано при описании макроструктуры алгоритма.&lt;br /&gt;
&lt;br /&gt;
Выполнение алгоритма включает в себя подготовительную стадию &#039;&#039;BUILD&#039;&#039; и итерационную стадию &#039;&#039;SWAP&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Стадия &#039;&#039;BUILD&#039;&#039;&#039;&#039;&#039; предназначена для построения начального множества медоидов и состоит в последовательном выполнении следующих шагов:&lt;br /&gt;
&lt;br /&gt;
1. Добавить в множество &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; объект, сумма расстояний от которого до всех остальных объектов минимальна (самый центральный объект):&lt;br /&gt;
 &amp;lt;math&amp;gt;S = S + \{ arg\min_{i \in U} \sum_{j \in U} d_{ij} \}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. Выбрать ещё &amp;lt;math&amp;gt;K-1&amp;lt;/math&amp;gt; медоидов следующим образом&lt;br /&gt;
 &amp;lt;math&amp;gt;S = S + \{ arg\max_{i \in U} \sum_{j \in U - \{i\}} C_{ij} \}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Стадия &#039;&#039;SWAP&#039;&#039;&#039;&#039;&#039; является итерационной, одна итерация состоит в попытке улучшить кластеризацию путём выполнения &#039;&#039;обмена&#039;&#039;. На каждой итерации выполняется операция &amp;lt;math&amp;gt;arg\min_{i \in S, h \in U} \sum_{j \in U + \{i\}} T_{ijh}&amp;lt;/math&amp;gt;. Если для найденной пары &amp;lt;math&amp;gt;i \in S&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;h \in U&amp;lt;/math&amp;gt; значение &amp;lt;math&amp;gt;\sum_{j \in U + \{i\}} T_{ijh}&amp;lt;/math&amp;gt; меньше ноля (это означает, что кластеризацию можно улучшить), то выполняется обмен &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го медоида и &amp;lt;math&amp;gt;h&amp;lt;/math&amp;gt;-го объекта. В противном случае дальнейшее улучшение кластеризации с помощью &#039;&#039;обмена&#039;&#039; невозможно и алгоритм завершает свою работу.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В результате работы алгоритма множество &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; будет содержать ровно &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; объектов – медоидов. Как было сказано &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-й объект лежит в том же кластере, что и его медоид: &amp;lt;math&amp;gt;arg\min_{i \in S} d_{ij}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Из математического описания алгоритма следует, что [[глоссарий#Вычислительное ядро|&#039;&#039;вычислительное ядро&#039;&#039;]] алгоритма сосредоточено в итерационной стадии &#039;&#039;SWAP&#039;&#039;. Одна итерация состоит в вычислении:&lt;br /&gt;
 &amp;lt;math&amp;gt;arg\min_{i \in S, h \in U} \sum_{j \in U + \{i\}} T_{ijh}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Смысл этого выражения в том, что выполняется выбор такой пары медоида &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; и объекта &amp;lt;math&amp;gt;h&amp;lt;/math&amp;gt; операция обмена которых приведёт к улучшению кластеризации или же делается вывод о невозможности такого обмена и работа алгоритма завершается.&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Для описания значений &amp;lt;math&amp;gt;C_{ij}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;T_{ijh}&amp;lt;/math&amp;gt; и способа их вычисления введём следующие обозначения (в дополнение к обозначениям, введённым в математическом описании алгоритма):&lt;br /&gt;
* &amp;lt;math&amp;gt;D_{i}&amp;lt;/math&amp;gt; – расстояние от &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го объекта до его медоида&lt;br /&gt;
* &amp;lt;math&amp;gt;E_{i}&amp;lt;/math&amp;gt; – расстояние от &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го объекта до второго ближайшего к нему медоида&lt;br /&gt;
&lt;br /&gt;
Очевидно, что для любых объектов верно неравенство &amp;lt;math&amp;gt;D_{i} &amp;lt;= E_{i}&amp;lt;/math&amp;gt;. Отметим также, что значения &amp;lt;math&amp;gt;D_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;E_{i}&amp;lt;/math&amp;gt; могут меняться при изменениях в множествах &amp;lt;math&amp;gt;U&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;, следовательно они должны пересчитываться после добавления нового медоида или выполнения операции &#039;&#039;обмена&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Значение &amp;lt;math&amp;gt;C_{ij}&amp;lt;/math&amp;gt; представляет собой число, на которое уменьшается значение &amp;lt;math&amp;gt;D_{j}&amp;lt;/math&amp;gt; в результате выбора &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го объекта в качестве медоида. Очевидно, что данное значение всегда неотрицательно. Для вычисления &amp;lt;math&amp;gt;C_{ij}&amp;lt;/math&amp;gt; следует рассмотреть два случая. В первом случае, когда &amp;lt;math&amp;gt;D_{j} &amp;lt;= d_{ij}&amp;lt;/math&amp;gt;, величина &amp;lt;math&amp;gt;D_{j}&amp;lt;/math&amp;gt; не изменится, т.к. ближайший к &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-му объекту медоид останется на том же расстоянии от него, следовательно будет справедливо равенство &amp;lt;math&amp;gt;C_{ij} = 0&amp;lt;/math&amp;gt;. Во втором случае, когда &amp;lt;math&amp;gt;D_{j} &amp;gt; d_{ij}&amp;lt;/math&amp;gt;, ближайшим к &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-му объекту медоидом станет новый выбранный медоид (&amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ый объект), следовательно будет справедливо равенство &amp;lt;math&amp;gt;C_{ij} = D_{j} - d_{ij}&amp;lt;/math&amp;gt;.&lt;br /&gt;
[[file:PAM_Cij.png|thumb|center|300px|Вычисление значения &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;T_{ijh}&amp;lt;/math&amp;gt; представляет собой число, которое добавляется к значению &amp;lt;math&amp;gt;D_{j}&amp;lt;/math&amp;gt; в результате выполнения операции &#039;&#039;обмена&#039;&#039; &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го медоида и &amp;lt;math&amp;gt;h&amp;lt;/math&amp;gt;-го объекта. Для вычисления &amp;lt;math&amp;gt;C_{ij}&amp;lt;/math&amp;gt; следует рассмотреть два случая. В первом  случае, когда &amp;lt;math&amp;gt;D_{j} = d_{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;-го объекта) может быть два варианта: &amp;lt;math&amp;gt;E_{j} &amp;lt;= d_{jh}&amp;lt;/math&amp;gt; (медоидом &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-го объекта станет второго ближайший к нему медоид), тогда справедливо равенство &amp;lt;math&amp;gt;T_{ijh} = E_{j} - D_{j}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;E_{j} &amp;gt; d_{jh}&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;-й объект), тогда справедливо равенство &amp;lt;math&amp;gt;T_{ijh} = d_{jh} - D_{j}&amp;lt;/math&amp;gt;. Во втором случае, когда &amp;lt;math&amp;gt;D_{j} != d_{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;-го объекта) также может быть два варианта: &amp;lt;math&amp;gt;D_{j} &amp;lt;= d_{jh}&amp;lt;/math&amp;gt; (медоид &amp;lt;math&amp;gt;j&amp;lt;/math&amp;gt;-го объекта не изменится), тогда справедливо равенство &amp;lt;math&amp;gt;T_{ijh} = 0&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D_{j} &amp;gt; d_{jh}&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;-й объект), тогда справедливо равенство &amp;lt;math&amp;gt;T_{ijh} = d_{jh} - D_{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;T_{ijh}&amp;lt;/math&amp;gt; может быть вычислено по формуле &amp;lt;math&amp;gt;T_{ijh} = min(E_{j}, d_{jh}) - D_{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;T_{ijh} = min(d_{jh} - D_{j}, 0)&amp;lt;/math&amp;gt;. В формулах выше &amp;lt;math&amp;gt;min(x, y)&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;
[[file:PAM_Tijh.png|thumb|center|550px|Вычисление значения &amp;lt;math&amp;gt;T_{ijh}&amp;lt;/math&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
В соответствии с математическим описанием алгоритм включает две стадии &#039;&#039;BUILD&#039;&#039; и &#039;&#039;SWAP&#039;&#039;. Рассмотрим реализацию каждой стадии. При описании реализации последовательного алгоритма на псевдокоде будем считать, что в программе поддерживаются следующие переменные:&lt;br /&gt;
 &amp;lt;math&amp;gt;d_{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;
 &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; – требуемое число кластеров&lt;br /&gt;
 &amp;lt;math&amp;gt;O&amp;lt;/math&amp;gt; – множество всех объектов&lt;br /&gt;
 &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; – множество медоидов&lt;br /&gt;
 &amp;lt;math&amp;gt;U&amp;lt;/math&amp;gt; – множество всех объектов, кроме медоидов &amp;lt;math&amp;gt;U = O - S&amp;lt;/math&amp;gt;&lt;br /&gt;
 &amp;lt;math&amp;gt;D_{i}&amp;lt;/math&amp;gt; – расстояние от &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го объекта до его медоида&lt;br /&gt;
 &amp;lt;math&amp;gt;E_{i}&amp;lt;/math&amp;gt; – расстояние от &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го объекта до второго ближайшего к нему медоида&lt;br /&gt;
&lt;br /&gt;
Значения &amp;lt;math&amp;gt;D_{i}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;E_{i}&amp;lt;/math&amp;gt; необходимо поддерживать для вычисления значений &amp;lt;math&amp;gt;C_{ij}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;T_{ijh}&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Реализация стадии &#039;&#039;BUILD&#039;&#039;:&lt;br /&gt;
 Найти первый медоид &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; как &amp;lt;math&amp;gt;arg\min_{i \in U} \sum_{j \in U} d_{ij}&amp;lt;/math&amp;gt;&lt;br /&gt;
 Инициализировать &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; как множество из одного объекта &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;&lt;br /&gt;
 Инициализировать &amp;lt;math&amp;gt;U&amp;lt;/math&amp;gt; как множество всех объектов, кроме объекта &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;&lt;br /&gt;
 Выполнить тело цикла &amp;lt;math&amp;gt;K-1&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;arg\max_{i \in U} \sum_{j \in U - \{i\}} C_{ij}&amp;lt;/math&amp;gt;&lt;br /&gt;
     Добавить к &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; объект &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;&lt;br /&gt;
     Убрать из &amp;lt;math&amp;gt;U&amp;lt;/math&amp;gt; объект &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt;&lt;br /&gt;
 Конец тела цикла&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Реализация стадии &#039;&#039;SWAP&#039;&#039;:&lt;br /&gt;
 Инициализировать флаг &#039;&#039;продолжить_счёт&#039;&#039; значением &#039;&#039;истина&#039;&#039;&lt;br /&gt;
 Выполнить цикл с предусловием пока флаг &#039;&#039;продолжить_счёт&#039;&#039; имеет значение &#039;&#039;истина&#039;&#039;&lt;br /&gt;
 Начало тела цикла&lt;br /&gt;
     Вычислить значения &amp;lt;math&amp;gt;D_{i}, E_{i}&amp;lt;/math&amp;gt; для всех объектов из множества &amp;lt;math&amp;gt;U&amp;lt;/math&amp;gt;&lt;br /&gt;
     Вычислить пару &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;h&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;arg\min_{i \in S, h \in U} \sum_{j \in U + \{i\}} T_{ijh}&amp;lt;/math&amp;gt;&lt;br /&gt;
     Если &amp;lt;math&amp;gt;\sum_{j \in U + \{i\}} T_{ijh} &amp;lt; 0&amp;lt;/math&amp;gt;, то выполнить обмен:&lt;br /&gt;
         Добавить в &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt; объект &amp;lt;math&amp;gt;h&amp;lt;/math&amp;gt; и убрать объект &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;&lt;br /&gt;
         Добавить в &amp;lt;math&amp;gt;U&amp;lt;/math&amp;gt; объект &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; и убрать объект &amp;lt;math&amp;gt;h&amp;lt;/math&amp;gt;&lt;br /&gt;
     Иначе&lt;br /&gt;
         Присвоить флагу &#039;&#039;продолжить_счёт&#039;&#039; значением &#039;&#039;ложь&#039;&#039;&lt;br /&gt;
 Конец тела цикла&lt;br /&gt;
&lt;br /&gt;
Реализация алгоритма в соответствии с данной схемой доступа на github[https://github.com/al-pacino/Clustering].&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; кластерам.&lt;br /&gt;
В соответствии с приведённым математическим описанием алгоритм включает в себя подготовительную стадию &#039;&#039;BUILD&#039;&#039; и итерационную стадию &#039;&#039;SWAP&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Стадия &#039;&#039;BUILD&#039;&#039; сводится к вычислению:&lt;br /&gt;
 Одной операции &amp;lt;math&amp;gt;arg\min_{i} \sum_{j} d_{ij}&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;arg\max_{i \in U} \sum_{j \in U - \{i\}} C_{ij}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Т.е. стадия &#039;&#039;BUILD&#039;&#039; требует:&lt;br /&gt;
 &amp;lt;math&amp;gt;K * N^2&amp;lt;/math&amp;gt; операций сложения&lt;br /&gt;
 &amp;lt;math&amp;gt;K * N&amp;lt;/math&amp;gt; операций сравнения (определения максимума/минимума)&lt;br /&gt;
 Около &amp;lt;math&amp;gt;K * N^2&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;SWAP&#039;&#039; сводится к вычислению:&lt;br /&gt;
 &amp;lt;math&amp;gt;arg\min_{i \in S, h \in U} \sum_{j \in U + \{i\}} T_{ijh}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Т.е. одна итерации стадии &#039;&#039;SWAP&#039;&#039; требует порядка:&lt;br /&gt;
 &amp;lt;math&amp;gt;K * N^2&amp;lt;/math&amp;gt; операций сложения&lt;br /&gt;
 &amp;lt;math&amp;gt;K * N&amp;lt;/math&amp;gt; операций сравнения (определения максимума/минимума)&lt;br /&gt;
 &amp;lt;math&amp;gt;K * (N - K) * (N - K - 1)&amp;lt;/math&amp;gt; вычислений &amp;lt;math&amp;gt;T_{ijh}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Вычисления &amp;lt;math&amp;gt;C_{ij}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;T_{ijh}&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;, поэтому сложность одной итерации алгоритма определяется как &amp;lt;math&amp;gt;O(K * N^2)&amp;lt;/math&amp;gt;. Таким образом можно отнести алгоритм &#039;&#039;PAM&#039;&#039; к алгоритмам с квадратичной сложностью по количеству &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; объектов.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
&lt;br /&gt;
На рисунке 1.7.1 показан информационный граф для итерации стадии &#039;&#039;SWAP&#039;&#039;. Опишем его аналитически. Нетрудно видеть, что граф состоит из &amp;lt;math&amp;gt;K * N&amp;lt;/math&amp;gt; групп, представляющих собой сумму &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; элементов. Суммы из разных групп не связаны между собой и в следствие этого могут быть вычислены параллельно на разных ядрах. Данное свойство хорошо отражает параллельную структуру алгоритма.&lt;br /&gt;
&lt;br /&gt;
[[file:PAM_graph_swap.png|thumb|center|600px|Рисунок 1.7.1. Информационный граф одной итерации стадии &#039;&#039;SWAP&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
На рисунке 1.7.2 показан информационный граф для выбора медоида на стадии &#039;&#039;BUILD&#039;&#039;. Его описание практически полностью совпадает с описанием графа для итерации стадии &#039;&#039;SWAP&#039;&#039;, за исключением того, что он содержит всего &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; групп сумм &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; элементов.&lt;br /&gt;
&lt;br /&gt;
[[file:PAM_graph_build.png|thumb|center|600px|Рисунок 1.7.2. Информационный граф выбора медоида стадии &#039;&#039;BUILD&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Исходя из предположения неограниченности ресурсов будем считать, что в нашем распоряжении имеется &amp;lt;math&amp;gt;N * K&amp;lt;/math&amp;gt; вычислительных ядер, память каждого из которых целиком содержит матрицу расстояния &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Стадия &#039;&#039;BUILD&#039;&#039; состоит из выбора начального (центрального) медоида и выбора &amp;lt;math&amp;gt;K - 1&amp;lt;/math&amp;gt; оставшихся медоидов. Для выбора медоида требуется вычисления &amp;lt;math&amp;gt;arg\max_{i \in U} \sum_{j \in U - \{i\}} C_{ij}&amp;lt;/math&amp;gt; (&amp;lt;math&amp;gt;arg\min_{i \in U} \sum_{j \in U} d_{ij}&amp;lt;/math&amp;gt;) для всех не выбранных объектов (из множества &amp;lt;math&amp;gt;U&amp;lt;/math&amp;gt;). Сумму в операции &amp;lt;math&amp;gt;arg\max&amp;lt;/math&amp;gt; (&amp;lt;math&amp;gt;arg\min&amp;lt;/math&amp;gt;) можно считать независимо на разных ядрах, поэтому сложность выбора одного медоида на стадии &#039;&#039;BUILD&#039;&#039; можно сократить с &amp;lt;math&amp;gt;O(N^2)&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt; (сложность вычисления суммы на одном ядре). Выбор одного медоида на стадии &#039;&#039;BUILD&#039;&#039; осуществляется &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; раз, следовательно, сложность параллельной реализации стадии &#039;&#039;BUILD&#039;&#039; (в соответствии с данным описанием) будет равна &amp;lt;math&amp;gt;O(K * N)&amp;lt;/math&amp;gt;. Также стоит отметить, что для выполнения стадии &#039;&#039;BUILD&#039;&#039; описанным выше образом, достаточно задействовать лишь &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вычислительных ядер, а не &amp;lt;math&amp;gt;N * K&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Проведём аналогичные рассуждения для одной итерации стадии &#039;&#039;SWAP&#039;&#039;. Выполнение одной итерации требует вычисления &amp;lt;math&amp;gt;arg\min_{i \in S, h \in U} \sum_{j \in U + \{i\}} T_{ijh}&amp;lt;/math&amp;gt; для каждой пары медоида и объекта. Сумму в операции &amp;lt;math&amp;gt;arg\min&amp;lt;/math&amp;gt; можно считать независимо на разных ядрах, поэтому сложность одной итерации стадии &#039;&#039;SWAP&#039;&#039; можно сократить с &amp;lt;math&amp;gt;O(K * N^2)&amp;lt;/math&amp;gt; до &amp;lt;math&amp;gt;O(N)&amp;lt;/math&amp;gt; если задействовать &amp;lt;math&amp;gt;N * K&amp;lt;/math&amp;gt; вычислительных ядер. Если в нашем распоряжении есть только &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вычислительных ядер, то сложность операции одной итерации стадии &#039;&#039;SWAP&#039;&#039; будет равна &amp;lt;math&amp;gt;O(K * N)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
В результате проведённых рассуждений можно сделать вывод о том, что сложность параллельной реализации алгоритма является линейной по числу объектов кластеризации &amp;lt;math&amp;gt;O(K * N)&amp;lt;/math&amp;gt; против квадратичной сложности &amp;lt;math&amp;gt;O(K * N^2)&amp;lt;/math&amp;gt; в последовательном случае.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Выполнение стадии &#039;&#039;BUILD&#039;&#039; состоит из &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; шагов.&lt;br /&gt;
Выполнение шага с номером &amp;lt;math&amp;gt;Step = 1,2,...,K&amp;lt;/math&amp;gt; включает следующие ярусы канонической ярусно-параллельной формы:&lt;br /&gt;
 При &amp;lt;math&amp;gt;Step = 1&amp;lt;/math&amp;gt;:&lt;br /&gt;
 1. &amp;lt;math&amp;gt;N - 1&amp;lt;/math&amp;gt; операций сложения&lt;br /&gt;
 2. &amp;lt;math&amp;gt;N - 1&amp;lt;/math&amp;gt; операций минимума двух чисел&lt;br /&gt;
&lt;br /&gt;
Максимальная ширину равную &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; имеет 1 ярус.&lt;br /&gt;
&lt;br /&gt;
 При &amp;lt;math&amp;gt;Step &amp;gt; 1&amp;lt;/math&amp;gt;:&lt;br /&gt;
 1. &amp;lt;math&amp;gt;N - Step&amp;lt;/math&amp;gt; операций вычитания&lt;br /&gt;
 2. &amp;lt;math&amp;gt;N - Step&amp;lt;/math&amp;gt; операций максимума&lt;br /&gt;
 3. &amp;lt;math&amp;gt;N - Step&amp;lt;/math&amp;gt; операций сложения&lt;br /&gt;
 4. &amp;lt;math&amp;gt;N - Step&amp;lt;/math&amp;gt; операций максимума&lt;br /&gt;
 5. Добавление нового медоида (не требует выполнения рассматриваемых операций)&lt;br /&gt;
&lt;br /&gt;
Максимальную ширину равную &amp;lt;math&amp;gt;N - Step + 1&amp;lt;/math&amp;gt; имеют ярусы 1, 2 и 3.&lt;br /&gt;
&lt;br /&gt;
Таким образом, параллельная сложность стадии &#039;&#039;BUILD&#039;&#039; включает:&lt;br /&gt;
 &amp;lt;math&amp;gt;2*N*K - K^2 - N - K + 1&amp;lt;/math&amp;gt; операций сложения (вычитания)&lt;br /&gt;
 &amp;lt;math&amp;gt;2*N*K - K^2 - N - K + 1&amp;lt;/math&amp;gt; операций максимума (минимума)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Выполнение одной итерации стадии &#039;&#039;SWAP&#039;&#039; включает следующие ярусы канонической ярусно-параллельной формы:&lt;br /&gt;
 1. &amp;lt;math&amp;gt;N - K + 1&amp;lt;/math&amp;gt; операций минимума&lt;br /&gt;
 2. &amp;lt;math&amp;gt;N - K + 1&amp;lt;/math&amp;gt; операций вычитания&lt;br /&gt;
 3. &amp;lt;math&amp;gt;N - K&amp;lt;/math&amp;gt; операций сложения&lt;br /&gt;
 4. &amp;lt;math&amp;gt;K * (N - K) - 1&amp;lt;/math&amp;gt; операций минимума&lt;br /&gt;
 5. Выполнение операции &#039;&#039;обмена&#039;&#039; (не требует выполнения рассматриваемых операций)&lt;br /&gt;
&lt;br /&gt;
Максимальную ширину равную &amp;lt;math&amp;gt;K * (N - K)&amp;lt;/math&amp;gt; имеют ярусы 1, 2 и 3.&lt;br /&gt;
&lt;br /&gt;
Таким образом, параллельная сложность стадии &#039;&#039;SWAP&#039;&#039; включает:&lt;br /&gt;
 &amp;lt;math&amp;gt;2*N - 2*K + 1&amp;lt;/math&amp;gt; операций сложения (вычитания)&lt;br /&gt;
 &amp;lt;math&amp;gt;N*K + N - K + 1&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. Матрица расстояния (в смысле непохожести) между объектами кластеризации (dissimilarity matrix) &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; (элементы &amp;lt;math&amp;gt;d_{ij}&amp;lt;/math&amp;gt;).&lt;br /&gt;
 Дополнительные ограничения:&lt;br /&gt;
    &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; – симметрическая матрица порядка &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, т.е. &amp;lt;math&amp;gt;d_{ij}= d_{ji}, i, j = 1, \ldots, N&amp;lt;/math&amp;gt;&lt;br /&gt;
    &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; – содержит нули на главной диагонали, т.е. &amp;lt;math&amp;gt;d_{ii}= 0, i = 1, \ldots, N&amp;lt;/math&amp;gt;&lt;br /&gt;
 2. &amp;lt;math&amp;gt;K&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;\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;
 &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; чисел &amp;lt;math&amp;gt;k_{1}, k_{2}, \ldots, k_{N}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;k_{i}&amp;lt;/math&amp;gt; - целое число, соответствующее кластеру &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-го объекта.&lt;br /&gt;
&lt;br /&gt;
 Выходными данными алгоритма также можно считать &amp;lt;math&amp;gt;K&amp;lt;/math&amp;gt; чисел, задающих номера объектов кластеризации, выделенных в качестве медоидов (medoids). Однако в большинстве случаев требуется именно определение кластеров объектов, а не поиск соответствующих медоидов.&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;
Соотношение последовательной и параллельной сложности в предположении о неограниченности ресурсов в описанном выше случае является линейным (отношение квадратичной сложности к линейной).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
При описании [[глоссарий#Вычислительная мощность|&#039;&#039;вычислительной мощности&#039;&#039;]] будем считать, что для завершения работы алгоритма &#039;&#039;PAM&#039;&#039; требуется выполнить &amp;lt;math&amp;gt;Q&amp;lt;/math&amp;gt; итераций стадии &#039;&#039;SWAP&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Последовательная [[глоссарий#Вычислительная мощность|&#039;&#039;вычислительная мощность&#039;&#039;]] как стадии &#039;&#039;BUILD&#039;&#039; так и одной итерации стадии &#039;&#039;SWAP&#039;&#039; равна &amp;lt;math&amp;gt;O(K)&amp;lt;/math&amp;gt;. Следовательно, последовательная [[глоссарий#Вычислительная мощность|&#039;&#039;вычислительная мощность&#039;&#039;]] алгоритма равна &amp;lt;math&amp;gt;O(Q * K)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Параллельная [[глоссарий#Вычислительная мощность|&#039;&#039;вычислительная мощность&#039;&#039;]] стадии &#039;&#039;BUILD&#039;&#039; и одной итерации стадии &#039;&#039;SWAP&#039;&#039;, в случае когда используется &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вычислительных узлов, равна &amp;lt;math&amp;gt;O(\frac{K}{N})&amp;lt;/math&amp;gt;. В случае когда используется &amp;lt;math&amp;gt;N * K&amp;lt;/math&amp;gt; вычислительных узлов для одной итерации стадии &#039;&#039;SWAP&#039;&#039; это значение снижается до &amp;lt;math&amp;gt;O(\frac{1}{N})&amp;lt;/math&amp;gt;. Следовательно, параллельная [[глоссарий#Вычислительная мощность|&#039;&#039;вычислительная мощность&#039;&#039;]] алгоритма равна &amp;lt;math&amp;gt;O(\frac{Q * K}{N})&amp;lt;/math&amp;gt;, в случае когда используется &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вычислительных узлов, и &amp;lt;math&amp;gt;O(\frac{Q + K}{N})&amp;lt;/math&amp;gt;, в случае когда используется &amp;lt;math&amp;gt;N * K&amp;lt;/math&amp;gt; вычислительных узлов.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;table border=&amp;quot;1&amp;quot; cellspacing=&amp;quot;0&amp;quot; cellpadding=&amp;quot;8&amp;quot; style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;caption&amp;gt;Таблица 1.10.1. [[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]] алгоритма&amp;lt;/caption&amp;gt;&lt;br /&gt;
&amp;lt;tr style=&amp;quot;background-color: #dedede;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;th&amp;gt;&#039;&#039;&#039;[[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]]&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
&amp;lt;th&amp;gt;&#039;&#039;&#039;Последовательной реализации&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
&amp;lt;th&amp;gt;&#039;&#039;&#039;Параллельной реализации&amp;lt;br&amp;gt;(&amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; вычислительных узлов)&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
&amp;lt;th&amp;gt;&#039;&#039;&#039;Параллельной реализации&amp;lt;br&amp;gt;(&amp;lt;math&amp;gt;N * K&amp;lt;/math&amp;gt; вычислительных узлов)&#039;&#039;&#039;&amp;lt;/th&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;Стадии &#039;&#039;BUILD&#039;&#039;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&amp;lt;math&amp;gt;O(K)&amp;lt;/math&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&amp;lt;math&amp;gt;O(\frac{K}{N})&amp;lt;/math&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&amp;lt;math&amp;gt;O(\frac{K}{N})&amp;lt;/math&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;Одной итерации стадии &#039;&#039;SWAP&#039;&#039;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&amp;lt;math&amp;gt;O(K)&amp;lt;/math&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&amp;lt;math&amp;gt;O(\frac{K}{N})&amp;lt;/math&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&amp;lt;math&amp;gt;O(\frac{1}{N})&amp;lt;/math&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;Алгоритма &#039;&#039;PAM&#039;&#039;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&amp;lt;math&amp;gt;O(Q * K)&amp;lt;/math&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&amp;lt;math&amp;gt;O(\frac{Q * K}{N})&amp;lt;/math&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;&amp;lt;math&amp;gt;O(\frac{Q + K}{N})&amp;lt;/math&amp;gt;&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Основные достоинства алгоритма &#039;&#039;PAM&#039;&#039;&#039;&#039;&#039;:&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;
&#039;&#039;&#039;Основные недостатки алгоритма &#039;&#039;PAM&#039;&#039;&#039;&#039;&#039;:&lt;br /&gt;
* Необходимо задание требуемого числа кластеров&lt;br /&gt;
* Квадратичная вычислительная сложность&lt;br /&gt;
&lt;br /&gt;
== Программная реализация алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
&lt;br /&gt;
Для исследования масштабируемости алгоритма &#039;&#039;PAM&#039;&#039; использовалась доступная на github[https://github.com/al-pacino/Clustering] реализация алгоритма. Исследование проводилось на суперкомпьютере BlueGene/P[http://hpc.cmc.msu.ru/bgp].&lt;br /&gt;
&lt;br /&gt;
Были измерено время выполнения для каждой из двух, составляющих всю программу, частей:&lt;br /&gt;
* Чтение и подготовка исходных данных&lt;br /&gt;
* Выполнение алгоритма &#039;&#039;PAM&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Для проведения измерений было подготовлено 6 наборов псевдослучайных данных, содержащих от 1024 до 6144 (с шагом 1024) объектов кластеризации. Измерения проводились для числа процессов равного 1 и кратного 4 в диапазоне от 1 до 256: 1, 4, 8, 16, ..., 252, 256.&lt;br /&gt;
&lt;br /&gt;
На рисунке 2.4.1 показана зависимость времени чтения и подготовки исходных данных от числа процессов и размера данных. График наглядно демонстрирует, что данное время в исследуемой реализации зависит лишь от объёма данных, но не от числа процессов. Также можно заметить небольшие шероховатости на графике, свидетельствующие о том, что данное время может незначительно изменяться от запуска к запуску.&lt;br /&gt;
[[file:PAM_time_read.png|thumb|center|1024px|Рисунок 2.4.1. Время чтения (в секундах) и подготовки исходных данных]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
На рисунке 2.4.2 показана зависимость времени работы алгоритма &#039;&#039;PAM&#039;&#039; от числа процессов и размера данных. График иллюстрирует хорошую масштабируемость алгоритма в случае, когда число объектов кластеризации превышает число процессов.&lt;br /&gt;
[[file:PAM_time_pam.png|thumb|center|1024px|Рисунок 2.4.2. Время (в секундах) выполнения алгоритма &#039;&#039;PAM&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
На рисунке 2.4.3 показана зависимость общего времени работы программы от числа процессов и размера данных. Заметно ухудшение масштабируемости по сравнению с графиком на рисунке 2.4.2.&lt;br /&gt;
[[file:PAM_time_whole.png|thumb|center|1024px|Рисунок 2.4.3. Общее время (в секундах) выполнения программы]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
На рисунке 2.4.4 показана зависимость эффективности алгоритма &#039;&#039;PAM&#039;&#039; от числа процессов и размера данных. График показывает, что эффективность снижается не очень быстро с ростом числа процессов, что также иллюстрирует хорошую масштабируемость алгоритма в случае, когда число объектов кластеризации превышает число процессов.&lt;br /&gt;
[[file:PAM_efficiency_pam.png|thumb|center|1024px|Рисунок 2.4.4. Эффективность (от 0 до 1) алгоритма &#039;&#039;PAM&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
На рисунке 2.4.5 показана зависимость эффективности работы всей программы от числа процессов и размера данных. Заметно ухудшение по сравнению с графиком на рисунке 2.4.4, за счёт добавления времени чтения и подготовки исходных данных. Эффективность заметно падает, с ростом числа процессов: время чтения и подготовки исходных данных остаётся неизменным, а время работы алгоритма &#039;&#039;PAM&#039;&#039; не даёт ускорения поскольку оно значительно меньше, чем время чтения и подготовки исходных данных (начиная с определённого числа процессов).&lt;br /&gt;
[[file:PAM_efficiency_whole.png|thumb|center|1024px|Рисунок 2.4.5. Эффективность (от 0 до 1) всей программы]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Масштабируемость рассматриваемой реализации алгоритма &#039;&#039;PAM&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
* При увеличении числа процессов общая эффективность программы уменьшается, т.к. время чтения и подготовки исходных данных остаётся неизменным и начинает преобладать над временем работы алгоритма &#039;&#039;PAM&#039;&#039;.&lt;br /&gt;
* При увеличении числа объектов кластеризации общая эффективность программы постепенно увеличивается, т.к. время чтения и подготовки исходных данных растёт медленнее, чем время работы алгоритма &#039;&#039;PAM&#039;&#039;.&lt;br /&gt;
* При одновременном увеличении как числа процессов, так и числа объектов кластеризации общая эффективность программы уменьшается.&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
# Последовательная реализация алгоритма PAM в пакете ClusterR на языке R:&lt;br /&gt;
#* Лицензия: MIT&lt;br /&gt;
#* [https://cran.r-project.org/package=ClusterR веб-страница фреймворка (исходный код, системные требования и справочное руководство)]&lt;br /&gt;
#* Алгоритм PAM реализован в функции &#039;Cluster_Medoids&#039;. Отличительная особенность реализации &amp;lt;ref&amp;gt;Lampros Mouselimis [https://cran.r-project.org/web/packages/cluster/cluster.pdf Package &#039;ClusterR&#039;]. October 8, 2016&amp;lt;/ref&amp;gt;:&lt;br /&gt;
#** для задания метрики между элементами кластеризуемого множества передаётся строка, задающая одну из реализованных в алгоритме метрик. Данный подход теряет одно из преимуществ алгоритма PAM, позволяющее в качестве матрицы расстояний использовать произвольную матрицу различий.&lt;br /&gt;
#:&lt;br /&gt;
#:&lt;br /&gt;
# Последовательная реализация алгоритма PAM в пакете Cluster на языке R:&lt;br /&gt;
#* Лицензия: GPL (≥2)&lt;br /&gt;
#* [https://cran.r-project.org/package=cluster веб-страница фреймворка (исходный код, системные требования и справочное руководство)]&lt;br /&gt;
#* Алгоритм PAM реализован в функции &#039;pam()&#039;. Данная реализация имеет следующие особенности &amp;lt;ref&amp;gt;Martin Maechler., etc. [https://cran.r-project.org/web/packages/cluster/cluster.pdf Package &#039;cluster&#039;]. October 8, 2016&amp;lt;/ref&amp;gt;:&lt;br /&gt;
#** функция может принимать на вход не множество точек, а матрицу расстояний между ними;&lt;br /&gt;
#** реализация более гибкая, так как принимает на вход матрицу различий элементов, а не использует какую-либо метрику;&lt;br /&gt;
#** может быть предоставлено графическое отображение.&lt;br /&gt;
#:&lt;br /&gt;
#:&lt;br /&gt;
#:&lt;br /&gt;
# Параллельная реализация алгоритма PAM в пакете SPRINT (Simple Parallel R INTerface - параллельный фреймворк) на языке R:&lt;br /&gt;
#* Лицензия: GPL (≥3)&lt;br /&gt;
#* [https://cran.r-project.org/package=sprint веб-страница фреймворка (исходный код, системные требования и справочное руководство)]&lt;br /&gt;
#* Алгоритм PAM реализован в фукции &#039;ppam()&#039;. Входные параметры данной функции схожи с параметрами, задаваемыми в линейной реализации &#039;pam()&#039; пакета Cluster языка R. Отличительной особенностью является подача на вход предвычисленной матрицы расстояний (например, с помощью функции &#039;pcor()&#039; из этой же библиотеки).&amp;lt;ref&amp;gt;University of Edinburgh SPRINT Team. [https://cran.r-project.org/web/packages/sprint/sprint.pdf Package &#039;sprint&#039;]. February 20, 2015&amp;lt;/ref&amp;gt;&lt;br /&gt;
#:&lt;br /&gt;
#:&lt;br /&gt;
# Параллельная реализация алгоритма PAM на основе операций MapReduce на Hadoop кластере.&lt;br /&gt;
#* В рамках исследования по ускорению анализа информации о геноме были созданы реализации алгоритма PAM с использованием технологии MPI и технологии MapReduce. Реализация в открытом досупе отсутствует. &amp;lt;ref&amp;gt;[Dobrzelecki B. et al. Managing and analysing Genomic Data using HPC and Clouds //Grid and Cloud Database Management. – Springer Berlin Heidelberg, 2011. – С. 261-277.&amp;lt;/ref&amp;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;/div&gt;</summary>
		<author><name>Dexter</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:Elena777mc&amp;diff=18163</id>
		<title>Обсуждение участника:Elena777mc</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:Elena777mc&amp;diff=18163"/>
		<updated>2016-11-18T14:34:44Z</updated>

		<summary type="html">&lt;p&gt;Dexter: Новая страница: «1) п1.1 - что такое плоское разбиение? Поясните  2) п1.2 - рисунок малоинформативный. Что такое…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;1) п1.1 - что такое плоское разбиение? Поясните&lt;br /&gt;
&lt;br /&gt;
2) п1.2 - рисунок малоинформативный. Что такое Border, Core и т.д.? Наверно, лучше сделать надписи по-русски, раз уж статья на русском&lt;br /&gt;
&lt;br /&gt;
3) п1.4 - про деревья здесь лишнее, макроструктура - это описание алгоритма с &amp;quot;птичьего полета&amp;quot;&lt;br /&gt;
&lt;br /&gt;
4) п1.5 вместо &amp;quot;ядровой объект&amp;quot; лучше &amp;quot;объект, являющийся ядром&amp;quot; ; вместо комментариев &amp;quot;// Вспомогательная функция&amp;quot; лучше сделать подписи к кускам кода&lt;br /&gt;
&lt;br /&gt;
5) п1.7 - что такое PDBSCAN? На рис.2 с разбиением не очень понятно, что значат разноцветные    &lt;br /&gt;
  прямоугольники.&lt;/div&gt;</summary>
		<author><name>Dexter</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:Dadrik&amp;diff=18162</id>
		<title>Обсуждение участника:Dadrik</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:Dadrik&amp;diff=18162"/>
		<updated>2016-11-18T14:30:43Z</updated>

		<summary type="html">&lt;p&gt;Dexter: Новая страница: «1) п 2.1 и 2.4 не заполнены  2) п 1.3 - здесь больше сказано о метрике Минковского и евклидовой; с…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;1) п 2.1 и 2.4 не заполнены&lt;br /&gt;
&lt;br /&gt;
2) п 1.3 - здесь больше сказано о метрике Минковского и евклидовой; сделайте более развернутым собственно описание вычислительного ядра алгоритма&lt;/div&gt;</summary>
		<author><name>Dexter</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=18078</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=18078"/>
		<updated>2016-11-18T10:09:12Z</updated>

		<summary type="html">&lt;p&gt;Dexter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Преподаватель 1|Dexter}} &lt;br /&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>Dexter</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%BD%D1%82%D0%BE%D0%BD_%D0%A2%D0%BE%D0%B4%D1%83%D0%B0/Partitioning_Around_Medoids_(PAM)&amp;diff=17804</id>
		<title>Обсуждение участника:Антон Тодуа/Partitioning Around Medoids (PAM)</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%BD%D1%82%D0%BE%D0%BD_%D0%A2%D0%BE%D0%B4%D1%83%D0%B0/Partitioning_Around_Medoids_(PAM)&amp;diff=17804"/>
		<updated>2016-11-16T19:53:16Z</updated>

		<summary type="html">&lt;p&gt;Dexter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* &#039;&#039;&#039;Замечания второго рецензента&#039;&#039;&#039;&lt;br /&gt;
* п1.4 - в формулах для T_{ijh} есть min, но непонятно, по какому индексу берется минимум&lt;br /&gt;
* как вычисляется d_{ij}, по какой метрике? Это нужно добавить&lt;br /&gt;
&lt;br /&gt;
1) Нет верхней врезки со свойствами последовательной и параллельной версии алгоритма (см. страницу-образец)&lt;br /&gt;
&amp;lt;br/&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;&amp;lt;b&amp;gt;ИСПРАВЛЕНО&amp;lt;/b&amp;gt;&amp;lt;/font&amp;gt;&lt;/div&gt;</summary>
		<author><name>Dexter</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%BD%D1%82%D0%BE%D0%BD_%D0%A2%D0%BE%D0%B4%D1%83%D0%B0/Partitioning_Around_Medoids_(PAM)&amp;diff=17799</id>
		<title>Обсуждение участника:Антон Тодуа/Partitioning Around Medoids (PAM)</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%BD%D1%82%D0%BE%D0%BD_%D0%A2%D0%BE%D0%B4%D1%83%D0%B0/Partitioning_Around_Medoids_(PAM)&amp;diff=17799"/>
		<updated>2016-11-16T19:44:21Z</updated>

		<summary type="html">&lt;p&gt;Dexter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* &#039;&#039;&#039;Замечания второго рецензента&#039;&#039;&#039;&lt;br /&gt;
* п1.4 - в формулах для T_{ijh} есть min, но непонятно, по какому индексу берется минимум&lt;br /&gt;
&lt;br /&gt;
1) Нет верхней врезки со свойствами последовательной и параллельной версии алгоритма (см. страницу-образец)&lt;br /&gt;
&amp;lt;br/&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;&amp;lt;b&amp;gt;ИСПРАВЛЕНО&amp;lt;/b&amp;gt;&amp;lt;/font&amp;gt;&lt;/div&gt;</summary>
		<author><name>Dexter</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:Denemmy&amp;diff=17795</id>
		<title>Обсуждение участника:Denemmy</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:Denemmy&amp;diff=17795"/>
		<updated>2016-11-16T19:38:07Z</updated>

		<summary type="html">&lt;p&gt;Dexter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;п. 1.4&lt;br /&gt;
 &lt;br /&gt;
* В описании евклидовой метрики d(a, b) достаточно короткой формы - со знаком &amp;quot;сигма&amp;quot;&lt;br /&gt;
&lt;br /&gt;
п. 1.10&lt;br /&gt;
&lt;br /&gt;
* Почему сказано о вычислительной мощности алгоритма к средних, а не алгоритма PAM?&lt;br /&gt;
&lt;br /&gt;
п. 2.4&lt;br /&gt;
&lt;br /&gt;
* нет описания аппаратной платформы&lt;br /&gt;
* нет указания на реализацию алгоритма (своя или сторонняя)&lt;br /&gt;
[[Участник:Zhum|Zhum]] ([[Обсуждение участника:Zhum|обсуждение]]) 10:16, 16 ноября 2016 (MSK)&lt;/div&gt;</summary>
		<author><name>Dexter</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:Denemmy&amp;diff=17794</id>
		<title>Обсуждение участника:Denemmy</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:Denemmy&amp;diff=17794"/>
		<updated>2016-11-16T19:35:42Z</updated>

		<summary type="html">&lt;p&gt;Dexter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;п. 1.4 &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;br /&gt;
[[Участник:Zhum|Zhum]] ([[Обсуждение участника:Zhum|обсуждение]]) 10:16, 16 ноября 2016 (MSK)&lt;/div&gt;</summary>
		<author><name>Dexter</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:Avasilenko/Partitioning_Around_Medoids_(PAM)&amp;diff=17792</id>
		<title>Обсуждение участника:Avasilenko/Partitioning Around Medoids (PAM)</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:Avasilenko/Partitioning_Around_Medoids_(PAM)&amp;diff=17792"/>
		<updated>2016-11-16T19:32:10Z</updated>

		<summary type="html">&lt;p&gt;Dexter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;п1.4 - почему используется то minimum, то min? Зачем такая сложная расшифровка минимума value по всем элементам Y?&lt;br /&gt;
&lt;br /&gt;
# Поясните, что значит &amp;quot;плоский алгоритм кластеризации&amp;quot; в п 1.1&lt;br /&gt;
#* &#039;&#039;добавлено определение плоской и иерархической кластеризации&#039;&#039;&lt;br /&gt;
# Что значит &amp;quot;множественные вычисления&amp;quot; в п 1.3?&lt;br /&gt;
#* &#039;&#039;фраза &amp;quot;множественные вычисления&amp;quot; употреблялось в значении &amp;quot;многочисленные вычисления&amp;quot; (по аналогии с тем как это делалось в эталонной статье &amp;quot;Разложение Холецкого&amp;quot;), в нашей статье фраза была заменена&#039;&#039;&lt;br /&gt;
# В п1.4 - нет определения функций minimum (или это просто min?) и value &lt;br /&gt;
#* &#039;&#039;minimum - это операция нахождения минимального среди нескольких значений, принимаемых некоторой функцией (наличие данной макрооперации обусловлено тем, что компьютер может одновременно вычислить лишь минимум 2-х чисел (посредством их сравнения)). Функция value при этом является любой (поэтому будет указываться при вызове minimum).&#039;&#039;&lt;br /&gt;
# Псевдокод в 1.5 - много общих фраз, нужно написать детальнее&lt;br /&gt;
#* &#039;&#039;псевдокод был детализирован&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Был оформлен параграф 2.3 &amp;quot;Возможные способы и особенности параллельной реализации алгоритма&amp;quot;. Согласно заданию он не требуется, поэтому является дополнительной частью, которая была оформлена (так уж получилось).&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Дописан параграф 2.4 &amp;quot;Масштабируемость алгоритма и его реализации&amp;quot;. Реализация написана самостоятельно. Сетка сгенерирована достаточно подробно для обнаружения &#039;особых точек&#039;, как рекомендовал Владимир Валентинович.&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Dexter</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:Avasilenko&amp;diff=17785</id>
		<title>Обсуждение участника:Avasilenko</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:Avasilenko&amp;diff=17785"/>
		<updated>2016-11-16T19:23:09Z</updated>

		<summary type="html">&lt;p&gt;Dexter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;п. 1.1&lt;br /&gt;
 проверьте формулу для E. Суммирование идет по j, но в слагаемых индекс j отсутствует&lt;br /&gt;
&lt;br /&gt;
п. 2.4&lt;br /&gt;
&lt;br /&gt;
* не указано, какая реализация алгоритма использовалась - собственная или библиотечная&lt;br /&gt;
*: [[Участник:Zhum|Zhum]] ([[Обсуждение участника:Zhum|обсуждение]]) 11:28, 16 ноября 2016 (MSK)&lt;br /&gt;
** &#039;&#039;Ссылка на реализацию была указана в конце параграфа. Явно добавили указание, что реализация собственная.&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Dexter</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: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=17776</id>
		<title>Обсуждение участника:MelLain/ЕМ-алгоритм (Тематическое моделирование)</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: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=17776"/>
		<updated>2016-11-16T18:34:56Z</updated>

		<summary type="html">&lt;p&gt;Dexter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;1) п1.2.2 Что такое n с двойной индексацией?&lt;br /&gt;
&lt;br /&gt;
2) Общие слова о модернизациях - плохой заголовок, переформулируйте&lt;br /&gt;
&lt;br /&gt;
3) п1.5 очень плохое выравнивание в псевдокоде&lt;br /&gt;
&lt;br /&gt;
4) Почему поэлементное умножение вектора на вектор обозначается так же как поэлементное деления вектора на вектор?&lt;/div&gt;</summary>
		<author><name>Dexter</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=17775</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=17775"/>
		<updated>2016-11-16T18:32:40Z</updated>

		<summary type="html">&lt;p&gt;Dexter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Преподаватель 1|Dexter}} &lt;br /&gt;
Авторы описания: [[Участник:Мария_Готман|Готман М.Л.]], [[Участник:Julia_lukashkina|Лукашкина Ю.Н.]]&lt;br /&gt;
&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&amp;lt;/math&amp;gt;, то есть 3 входных объекта. &lt;br /&gt;
&lt;br /&gt;
На рис.1 показана макроструктура EM-алгоритма. Входными данными в таком случае являются матрица &amp;lt;math&amp;gt;X \in \R^{3 \times d}&amp;lt;/math&amp;gt;, число кластеров &amp;lt;math&amp;gt;= K&amp;lt;/math&amp;gt;,  число признаков &amp;lt;math&amp;gt;=d&amp;lt;/math&amp;gt;. &lt;br /&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 d}&amp;lt;/math&amp;gt; являются строчками входной матрицы &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt;, также на вход подаются текущие приближения векторов средних значений (&amp;lt;math&amp;gt;\mu_1, \dots, \;\mu_K&amp;lt;/math&amp;gt;), матриц ковариаций (&amp;lt;math&amp;gt;\Sigma_1, \dots, \Sigma_K&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,\dots,K&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,\dots,K&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,\dots,K&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 d}&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_{1K},\;g_{2K},\;g_{3K},\;\mu_K&amp;lt;/math&amp;gt; — для K-ого кластера.&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,\dots,\;\mu_K&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,\;\dots,\;\Sigma_K&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,\dots,\;w_K&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[file:EM M step2.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;
Для проведения экспериментов по масштабируемости были выбраны следующие параметры алгоритма: были зафиксированы число кластеров &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;
При увеличении числа процессоров производительность растёт. Заметим также, что с увеличением числа точек, скорость работы программы линейно увеличивается.&lt;br /&gt;
&lt;br /&gt;
[[file:EM-ef-time.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|Рис. 5 Эффективность EM алгоритма в зависимости от числа процессов и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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>Dexter</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=17774</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=17774"/>
		<updated>2016-11-16T18:32:16Z</updated>

		<summary type="html">&lt;p&gt;Dexter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Преподаватель 1|Dexter}} &lt;br /&gt;
Авторы описания: [[Участник:Мария_Готман|Готман М.Л.]], [[Участник:Julia_lukashkina|Лукашкина Ю.Н.]]&lt;br /&gt;
&lt;br /&gt;
{{Assignment}}&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&amp;lt;/math&amp;gt;, то есть 3 входных объекта. &lt;br /&gt;
&lt;br /&gt;
На рис.1 показана макроструктура EM-алгоритма. Входными данными в таком случае являются матрица &amp;lt;math&amp;gt;X \in \R^{3 \times d}&amp;lt;/math&amp;gt;, число кластеров &amp;lt;math&amp;gt;= K&amp;lt;/math&amp;gt;,  число признаков &amp;lt;math&amp;gt;=d&amp;lt;/math&amp;gt;. &lt;br /&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 d}&amp;lt;/math&amp;gt; являются строчками входной матрицы &amp;lt;math&amp;gt;X&amp;lt;/math&amp;gt;, также на вход подаются текущие приближения векторов средних значений (&amp;lt;math&amp;gt;\mu_1, \dots, \;\mu_K&amp;lt;/math&amp;gt;), матриц ковариаций (&amp;lt;math&amp;gt;\Sigma_1, \dots, \Sigma_K&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,\dots,K&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,\dots,K&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,\dots,K&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 d}&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_{1K},\;g_{2K},\;g_{3K},\;\mu_K&amp;lt;/math&amp;gt; — для K-ого кластера.&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,\dots,\;\mu_K&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,\;\dots,\;\Sigma_K&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,\dots,\;w_K&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[file:EM M step2.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;
Для проведения экспериментов по масштабируемости были выбраны следующие параметры алгоритма: были зафиксированы число кластеров &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;
При увеличении числа процессоров производительность растёт. Заметим также, что с увеличением числа точек, скорость работы программы линейно увеличивается.&lt;br /&gt;
&lt;br /&gt;
[[file:EM-ef-time.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|Рис. 5 Эффективность EM алгоритма в зависимости от числа процессов и размера задачи]]&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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>Dexter</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=17773</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=17773"/>
		<updated>2016-11-16T18:31:07Z</updated>

		<summary type="html">&lt;p&gt;Dexter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Преподаватель 1|Dexter}} &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{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>Dexter</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=17772</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=17772"/>
		<updated>2016-11-16T18:30:16Z</updated>

		<summary type="html">&lt;p&gt;Dexter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment|Преподаватель 1|Dexter}} &lt;br /&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 также эффективно распараллеливается по объектам с последующей агрегацией результатов по кластерам: параллельная сложность M-шага — &amp;lt;math&amp;gt;O(k * n)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Таким образом, параллельная сложность EM-алгоритма — &amp;lt;math&amp;gt;O(imax * k * n^{2})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039; плотная матрица объектов-признаков &amp;lt;math&amp;gt;X \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;
Исследование масштабируемости параллельной реализации EM-алгоритма проводилось на суперкомпьютере Blue Gene/P. Для этого использовалась собственная реализация алгоритма, написанная на языке C++ с использованием технологий MPI и OpenMP.&lt;br /&gt;
&lt;br /&gt;
Для проведения исследования были сгенерированы наборы данных из смеси двух двумерных нормальных распределений с диагональными матрицами ковариаций.&lt;br /&gt;
&lt;br /&gt;
Набор значений параметров запуска реализации алгоритма:&lt;br /&gt;
* число процессоров: 1, 8, 16, 32, 48, 64, 80, 96, 112, 128&lt;br /&gt;
* число элементов выборки: 1000, 25000, 50000, 75000, 100000, 200000, 300000, 400000, 500000, 600000, 700000, 800000, 900000, 1000000&lt;br /&gt;
* размерность пространства признаков: 2&lt;br /&gt;
* число кластеров: 2&lt;br /&gt;
* максимальное число итераций: MAX_INT&lt;br /&gt;
* минимальная величина изменения логарифма правдоподобия: 1e-6&lt;br /&gt;
&lt;br /&gt;
Начальные значения параметров смеси задавались следующим образом:&lt;br /&gt;
* центры кластеров - случайные элементы выборки&lt;br /&gt;
* матрицы ковариаций - единичные&lt;br /&gt;
* веса компонент равны между собой&lt;br /&gt;
&lt;br /&gt;
В связи с тем, что время и результат работы алгоритма сильно зависят от рандомизированной начальной инициализации центров кластеров, для каждого фиксированного набора параметров производилось по 25 запусков программы. В качестве итогового времени работы выбиралось минимальное время среди всех запусков.&lt;br /&gt;
&lt;br /&gt;
На рисунке 4 изображена зависимость времени работы алгоритма от числа процессоров и числа элементов выборки.&lt;br /&gt;
&lt;br /&gt;
[[File:EM_time.png|thumb|center|1200px|Рисунок 4. Зависимость времени работы параллельной реализации EM-алгоритма от числа процессоров и числа элементов выборки.]]&lt;br /&gt;
&lt;br /&gt;
Как видно из рисунка 4, при фиксированном числе процессоров зависимость времени выполнения от количества объектов выборки очень близка к линейной, что хорошо согласуется с теоретической оценкой.&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>Dexter</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:Elmon/%D0%9F%D0%BB%D0%BE%D1%82%D0%BD%D0%BE%D1%81%D1%82%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_DBSCAN&amp;diff=17057</id>
		<title>Обсуждение участника:Elmon/Плотностный алгоритм кластеризации DBSCAN</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:Elmon/%D0%9F%D0%BB%D0%BE%D1%82%D0%BD%D0%BE%D1%81%D1%82%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_DBSCAN&amp;diff=17057"/>
		<updated>2016-11-14T15:49:29Z</updated>

		<summary type="html">&lt;p&gt;Dexter: Новая страница: «1) Проверьте орфографию и грамматику - встречаются фразы типа &amp;quot;Выбирается произвольная н…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;1) Проверьте орфографию и грамматику - встречаются фразы типа &amp;quot;Выбирается произвольная непосещенный&amp;quot;&lt;br /&gt;
&lt;br /&gt;
2) Явно не сказано, что такое n&lt;/div&gt;</summary>
		<author><name>Dexter</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:Elena777mc/%D0%9F%D0%BB%D0%BE%D1%82%D0%BD%D0%BE%D1%81%D1%82%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_DBSCAN&amp;diff=17047</id>
		<title>Обсуждение участника:Elena777mc/Плотностный алгоритм кластеризации DBSCAN</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:Elena777mc/%D0%9F%D0%BB%D0%BE%D1%82%D0%BD%D0%BE%D1%81%D1%82%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_DBSCAN&amp;diff=17047"/>
		<updated>2016-11-14T15:23:15Z</updated>

		<summary type="html">&lt;p&gt;Dexter: Новая страница: «1) п1.1 - что такое плоское разбиение? Поясните  2) п1.2 - рисунок малоинформативный. Что такое…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;1) п1.1 - что такое плоское разбиение? Поясните&lt;br /&gt;
&lt;br /&gt;
2) п1.2 - рисунок малоинформативный. Что такое Border, Core и т.д.? Наверно, лучше сделать надписи по-русски, раз уж статья на русском&lt;br /&gt;
&lt;br /&gt;
3) п1.4 - про деревья здесь лишнее, макроструктура - это описание алгоритма с &amp;quot;птичьего полета&amp;quot;&lt;br /&gt;
&lt;br /&gt;
4) п1.5 вместо &amp;quot;ядровой объект&amp;quot; лучше &amp;quot;объект, являющийся ядром&amp;quot; ; вместо комментариев &amp;quot;// Вспомогательная функция&amp;quot; лучше сделать подписи к кускам кода&lt;br /&gt;
&lt;br /&gt;
5) п1.7 - что такое PDBSCAN? На рис.2 с разбиением не очень понятно, что значат разноцветные    &lt;br /&gt;
  прямоугольники.&lt;/div&gt;</summary>
		<author><name>Dexter</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: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=17034</id>
		<title>Обсуждение участника:MelLain/ЕМ-алгоритм (Тематическое моделирование)</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: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=17034"/>
		<updated>2016-11-14T15:04:42Z</updated>

		<summary type="html">&lt;p&gt;Dexter: Новая страница: «1) п1.2.2 Что такое n с двойной индексацией?  2) Общие слова о модернизациях - плохой заголовок…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;1) п1.2.2 Что такое n с двойной индексацией?&lt;br /&gt;
&lt;br /&gt;
2) Общие слова о модернизациях - плохой заголовок, переформулируйте&lt;br /&gt;
&lt;br /&gt;
3) п1.5 очень плохое выравнивание в псевдокоде&lt;br /&gt;
&lt;br /&gt;
4) Почему поэлементное умножение вектора на вектор обозначается так же как поэлементное деления &lt;br /&gt;
   вектора на вектор?&lt;/div&gt;</summary>
		<author><name>Dexter</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=16523</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=16523"/>
		<updated>2016-11-12T10:00:32Z</updated>

		<summary type="html">&lt;p&gt;Dexter: &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;/div&gt;</summary>
		<author><name>Dexter</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=16519</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=16519"/>
		<updated>2016-11-12T09:25:52Z</updated>

		<summary type="html">&lt;p&gt;Dexter: /* Замечания к Участник:Noite/EM-алгоритм_кластеризации */&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;
3)&#039;&#039;&#039;Ниже - замечания второго рецензента&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
4) Во врезке так и не появилась информация по поводу параллельного алгоритма&lt;br /&gt;
&lt;br /&gt;
5)Из содержания нужно убрать ссылку [5]&lt;br /&gt;
&lt;br /&gt;
6) В формулировке задачи в п1.1 нет разъяснения параметра m&lt;br /&gt;
&lt;br /&gt;
7) В п1.2 парметры m, n, k почему-то превратились в M, N, K  &lt;br /&gt;
&lt;br /&gt;
8) П 1.5. Как инициализируются скрытые переменные gamma? Выравнивание псевдокода местами нарушено. Слово &amp;quot;большУю&amp;quot; - здесь лучше использовать значок ударения&lt;br /&gt;
&lt;br /&gt;
9) П 1.7 Информационный граф: на рисунке омега превратилась в w, гамма - в Y.&lt;br /&gt;
&lt;br /&gt;
10)П 1.9 Выходные данные - сказано о векторе n. Поясните, какое значение он имеет в терминах алгоритма кластеризации.&lt;/div&gt;</summary>
		<author><name>Dexter</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:Maria_Zaitseva/PAM_(Partitioning_Around_Medoids)&amp;diff=16077</id>
		<title>Обсуждение участника:Maria Zaitseva/PAM (Partitioning Around Medoids)</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:Maria_Zaitseva/PAM_(Partitioning_Around_Medoids)&amp;diff=16077"/>
		<updated>2016-11-07T20:20:35Z</updated>

		<summary type="html">&lt;p&gt;Dexter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;1) В верхней врезке нет свойств параллельной версии алгоритма (см страницу-образец)&lt;br /&gt;
&lt;br /&gt;
2) Называть множества маленькими буквами - плохая идея&lt;br /&gt;
&lt;br /&gt;
3) На рис.2 показана ситуация для шага t, но буква t не участвует в подписях на рисунке&lt;/div&gt;</summary>
		<author><name>Dexter</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%BD%D1%82%D0%BE%D0%BD_%D0%A2%D0%BE%D0%B4%D1%83%D0%B0/Partitioning_Around_Medoids_(PAM)&amp;diff=15958</id>
		<title>Обсуждение участника:Антон Тодуа/Partitioning Around Medoids (PAM)</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%BD%D1%82%D0%BE%D0%BD_%D0%A2%D0%BE%D0%B4%D1%83%D0%B0/Partitioning_Around_Medoids_(PAM)&amp;diff=15958"/>
		<updated>2016-11-05T18:48:44Z</updated>

		<summary type="html">&lt;p&gt;Dexter: Новая страница: «1) Нет верхней врезки со свойствами последовательной и параллельной версии алгоритма (см…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;1) Нет верхней врезки со свойствами последовательной и параллельной версии алгоритма (см. страницу-образец)&lt;/div&gt;</summary>
		<author><name>Dexter</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:Maria_Zaitseva/PAM_(Partitioning_Around_Medoids)&amp;diff=15957</id>
		<title>Обсуждение участника:Maria Zaitseva/PAM (Partitioning Around Medoids)</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:Maria_Zaitseva/PAM_(Partitioning_Around_Medoids)&amp;diff=15957"/>
		<updated>2016-11-05T18:47:44Z</updated>

		<summary type="html">&lt;p&gt;Dexter: Новая страница: «1) В верхней врезке нет свойств параллельной версии алгоритма (см страницу-образец)»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;1) В верхней врезке нет свойств параллельной версии алгоритма (см страницу-образец)&lt;/div&gt;</summary>
		<author><name>Dexter</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:Avasilenko/Partitioning_Around_Medoids_(PAM)&amp;diff=15956</id>
		<title>Обсуждение участника:Avasilenko/Partitioning Around Medoids (PAM)</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:Avasilenko/Partitioning_Around_Medoids_(PAM)&amp;diff=15956"/>
		<updated>2016-11-05T18:31:14Z</updated>

		<summary type="html">&lt;p&gt;Dexter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;1) Поясните, что значит &amp;quot;плоский алгоритм кластеризации&amp;quot; в п 1.1&lt;br /&gt;
&lt;br /&gt;
2) Что значит &amp;quot;множественные вычисления &amp;quot; в п 1.3?&lt;br /&gt;
&lt;br /&gt;
3) В п1.4 - нет определения функций minimum (или это просто min?) и value &lt;br /&gt;
&lt;br /&gt;
4) Псевдокод в 1.5 - много общих фраз, нужно написать детальнее&lt;/div&gt;</summary>
		<author><name>Dexter</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:Avasilenko/Partitioning_Around_Medoids_(PAM)&amp;diff=15955</id>
		<title>Обсуждение участника:Avasilenko/Partitioning Around Medoids (PAM)</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:Avasilenko/Partitioning_Around_Medoids_(PAM)&amp;diff=15955"/>
		<updated>2016-11-05T18:24:27Z</updated>

		<summary type="html">&lt;p&gt;Dexter: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;1) Поясните, что значит &amp;quot;плоский алгоритм кластеризации&amp;quot; в п 1.1&lt;br /&gt;
&lt;br /&gt;
2) Что значит &amp;quot;множественные вычисления &amp;quot; в п 1.3?&lt;/div&gt;</summary>
		<author><name>Dexter</name></author>
	</entry>
</feed>