<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
	<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0+%D0%9C%D0%BE%D1%80%D0%BE%D0%B7%D0%BE%D0%B2%D0%B0</id>
	<title>Алговики - Вклад [ru]</title>
	<link rel="self" type="application/atom+xml" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0+%D0%9C%D0%BE%D1%80%D0%BE%D0%B7%D0%BE%D0%B2%D0%B0"/>
	<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/ru/%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/%D0%A1%D0%B2%D0%B5%D1%82%D0%BB%D0%B0%D0%BD%D0%B0_%D0%9C%D0%BE%D1%80%D0%BE%D0%B7%D0%BE%D0%B2%D0%B0"/>
	<updated>2026-10-22T23:30:10Z</updated>
	<subtitle>Вклад</subtitle>
	<generator>MediaWiki 1.43.5</generator>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=20643</id>
		<title>Участник:Smirnov.maxim/BIRCH</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=20643"/>
		<updated>2016-12-11T16:32:20Z</updated>

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

		<summary type="html">&lt;p&gt;Светлана Морозова: /* Последовательная сложность алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Авторы: [[Участник:Светлана Морозова|Морозова Светлана]], [[Участник:Smirnov.maxim|Смирнов Максим]].&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Нахождение полезных для анализа закономерностей в больших объёмах данных с недавних пор вызывает значительный интерес. В связи с этим ввелось и стало активно развиваться такое понятие как &#039;&#039;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7 кластеризация]&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Ранние работы и алгоритмы, разработанные в этой области, не уделяли достаточного внимания анализу очень больших наборов данных или минимизации издержек на процессы ввода-вывода.&lt;br /&gt;
Решением этих проблем стал алгоритм, известный как BIRCH.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIRCH&#039;&#039;&#039;&amp;lt;ref&amp;gt;[http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf Нейский И.М. Классификация и сравнение методов кластеризации]&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;[http://www.cs.sfu.ca/CourseCentral/459/han/papers/zhang96.pdf T Zhang, R Ramakrishnan, M Livny. BIRCH: An Efficient Data Clustering Method for Very Large Databases]&amp;lt;/ref&amp;gt; (balanced iterative reducing and clustering using hierarchies)- алгоритм, применяемый в области [https://ru.wikipedia.org/wiki/Data_mining Data mining] и использующий принципы [https://ru.wikipedia.org/wiki/%D0%98%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F иерархической кластеризации].&lt;br /&gt;
&lt;br /&gt;
Если имеется очень большой набор данных, то в пространстве он распределен, как правило, неравномерно. Кластерный анализ определяет места наибольшего и наименьшего скоплений, чтобы таким образом понять всю картину целиком. Кроме того, полученные кластеры визуализируются гораздо нагляднее, чем начальные &amp;quot;сырые&amp;quot; данные.&lt;br /&gt;
Задачей алгоритмов кластеризации является не только простое разбиение данных на кластеры, но и работа в рамках ограниченного объёма доступной памяти (как правило, её объём гораздо меньше, чем размер исходного набора данных) и минимизация времени, требуемого на операции ввода-вывода.&lt;br /&gt;
&lt;br /&gt;
Для наилучшего решения этих проблем BIRCH распределяет входящие данные по кластерам динамически. Для эффективной кластеризации алгоритму требуется всего одно сканирование данных (т.е. с увеличением количества данных сложность увеличивается линейно). А при помощи одной (или более) дополнительных итераций можно и далее улучшать эффективность. BIRCH также является первым алгоритмом, предложенным для эффективного управления &amp;quot;шумами&amp;quot; (данными, которые не вписываются в общее представление модели).&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Теоретическая основа ===&lt;br /&gt;
&lt;br /&gt;
Пусть в кластере имеются &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}, i=1,2,...,N&amp;lt;/math&amp;gt;.&lt;br /&gt;
Тогда &#039;&#039;&#039;центроид&#039;&#039;&#039; &amp;lt;math&amp;gt;{\vec{{X_0}}}&amp;lt;/math&amp;gt;, &#039;&#039;&#039;радиус&#039;&#039;&#039; &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &#039;&#039;&#039;диаметр&#039;&#039;&#039; &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластера определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;{\vec{X_0}}=\frac{\sum_{i=1}^N\vec{X_i}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{\sum_{i=1}^N{(\vec{X_i} - \vec{X_0})}^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{\sum_{i=1}^N\sum_{j=1}^N{(\vec{X_i} - \vec{X_j})}^2}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; - это среднее расстояние от каждой точки до центроида. &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; - это среднее расстояние между парами в кластере. Данные величины являются альтернативными метриками плотности кластера относительно центроида.&lt;br /&gt;
&lt;br /&gt;
Для измерения близости друг к другу двух кластеров вводятся следующие метрики:&lt;br /&gt;
&lt;br /&gt;
пусть даны центроиды двух кластеров &amp;lt;math&amp;gt;\vec{X_{01}}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\vec{X_{02}}&amp;lt;/math&amp;gt;.&lt;br /&gt;
Евклидова метрика &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt; и метрика Манхэттена &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt; между двумя кластерами определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_0 = ((\vec{X_{01}}-\vec{X_{02}})^2)^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_1 = |\vec{X_{01}}-\vec{X_{02}}| = \sum_{i=1}^d |{\vec{X_{01}}}^{(i)}-{\vec{X_{02}}}^{(i)}| &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть имеются два кластера, содержащих соответственно  &amp;lt;math&amp;gt;N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;N_2&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i= 1,2, ...,N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\{\vec{X_j}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j= N_1+1,N_1+2, ...,N_1+N_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Среднее расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &#039;&#039;&#039;среднее внутрикластерное расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &#039;&#039;&#039;дисперсия&#039;&#039;&#039; &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; для двух кластеров определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{\sum_{i=1}^{N_1}\sum_{j=N_1+1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{N_1N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{\sum_{i=1}^{N_1+N_2}\sum_{j=1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_4 = \sum_{k=1}^{N_1+N_2}(\vec{X_k} - \frac{\sum_{i=1}^{N_1+N_2}\vec{X_i}}{N_1+N_2})^2 - \sum_{i=1}^{N_1}(\vec{X_i} - \frac{\sum_{i=1}^{N_1}\vec{X_i}}{N_1})^2 - \sum_{j=N_1+1}^{N_1+N_2}(\vec{X_j} - \frac{\sum_{i=N_1+1}^{N_1+N_2}\vec{X_i}}{N_2})^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Таким образом, величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; относятся к отдельным кластерам, а &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; - к объединению двух кластеров.&lt;br /&gt;
&lt;br /&gt;
=== Кластерный элемент и кластерное дерево ===&lt;br /&gt;
&lt;br /&gt;
В основе концепции алгоритма BIRCH лежат понятия &#039;&#039;&#039;кластерного элемента&#039;&#039;&#039; и &#039;&#039;&#039;кластерного дерева (CF Tree)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====Кластерный элемент ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; Пусть в кластере содержатся  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности  &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;:&amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;i=1,2,...,N&amp;lt;/math&amp;gt;. &lt;br /&gt;
&#039;&#039;&#039;Кластерный элемент (CF)&#039;&#039;&#039; - тройка чисел, характеризующая информацию о кластере: &lt;br /&gt;
&amp;lt;math&amp;gt;CF = (N, \vec{LS}, SS)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - количество элементов входных данных, содержащихся в кластере, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; - линейная сумма входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}\vec{X_i}&amp;lt;/math&amp;gt;), &amp;lt;math&amp;gt;SS&amp;lt;/math&amp;gt; - сумма квадратов входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}{\vec{X_i}}^2&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Теорема&#039;&#039;&#039; Пусть &amp;lt;math&amp;gt;CF_1 = (N_1, \vec{LS_1}, SS_1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;CF_2 = (N_1, \vec{LS_2}, SS_2)&amp;lt;/math&amp;gt; - CF векторы двух непересекающихся кластеров. Тогда при их объединении образуется кластер со следующим CF вектором: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF = CF_1 + CF_2 = (N_1+N_2, \vec{LS_1}+\vec{LS_2}, SS_1+SS_2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Из указанных выше определения и теоремы вытекает тот факт, что при объединении кластеров их CF вектор может вычисляться инкрементно и точно. &lt;br /&gt;
Легко показать, что вычислить величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;, как и обычные метрики, также не составит труда.&lt;br /&gt;
&lt;br /&gt;
Таким образом, в данном случае информацией о кластере является не весь набор точек, а вектор CF. Хранение одного только вектора может показаться неэффективным, но этого вполне достаточно для оперирования всеми необходимыми метриками, на основе которых принимаются решения в алгоритме BIRCH.&lt;br /&gt;
&lt;br /&gt;
==== Кластерное дерево ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; &#039;&#039;&#039;Кластерное дерево (CF Tree)&#039;&#039;&#039; - это взвешенно сбалансированное дерево с двумя параметрами: &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - коэффициент разветвления, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - пороговая величина.&lt;br /&gt;
&lt;br /&gt;
Каждый нелистьевой узел дерева имеет не более чем &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; вхождений узлов следующей формы: &amp;lt;math&amp;gt;[CF_i,child_i]&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i=1,2,...,B&amp;lt;/math&amp;gt;, &#039;&#039;child&#039;&#039; - указатель на i-й дочерний узел, &amp;lt;math&amp;gt;CF_i&amp;lt;/math&amp;gt; - CF вектор соответствующего подкластера.&lt;br /&gt;
&lt;br /&gt;
Каждый листьевой узел имеет ссылку на два соседних узла (&#039;&#039;prev&#039;&#039; и &#039;&#039;next&#039;&#039;) для того, чтобы связать все узлы для эффективного сканирования.&lt;br /&gt;
Все листьевые узлы должны удовлетворять пороговому ограничению &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, т.е. диаметр (радиус) не должен превосходить &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;.&lt;br /&gt;
В процессе вставки новых данных CF дерево строится динамически. Оно использует вставку данных для кластеризации точно также как &amp;lt;math&amp;gt;B+&amp;lt;/math&amp;gt; [https://ru.wikipedia.org/wiki/B%2B-%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE дерево] использует её для поиска.&lt;br /&gt;
CF дерево очень компактно, поскольку каждый листьевой узел - это не просто точка, а подкластер (который объединяет множество точек с учётом ограничения &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Операция вставки в &#039;&#039;&#039;CF&#039;&#039;&#039; дерево ====&lt;br /&gt;
&lt;br /&gt;
Опишем алгоритм вставки элемнта &amp;lt;math&amp;gt;Ent&amp;lt;/math&amp;gt; в CF дерево:&lt;br /&gt;
&lt;br /&gt;
1) &#039;&#039;Определение подходящего листа&#039;&#039;: Начиная с корня, алгоритм рекурсивно спускается по CF дереву, выбирая &#039;&#039;&#039;ближайший&#039;&#039;&#039; дочерний узел в соответствии с выбранной метрикой &amp;lt;math&amp;gt;D0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D4&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &#039;&#039;Преобразование листа&#039;&#039;: Когда алгоритм доходит до листа, он находит ближайшую листьевой элемент, скажем, &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;, а затем проверяет, можно ли добавить &#039;&#039;Ent&#039;&#039; к &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt; без нарушения порогового условия. Если да, то с учётом этого изменяется CF вектор для &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;; если нет, то &#039;&#039;Ent&#039;&#039; становится новым элементом листа. Если в листе для этого достаточно места, то шаг окончен, иначе он должен &amp;quot;расщепиться&amp;quot;. Расщепление узла производится при помощи выбора за основу наиболее удалённой друг от друга пары элементов и перераспределение оставшихся элементов в соответствии с выбранным критерием близости.&lt;br /&gt;
&lt;br /&gt;
3) &#039;&#039;Преобразование пути к листу&#039;&#039;: После вставки &#039;&#039;Ent&#039;&#039; в лист мы должны обновить информацию о CF для каждого нелистьевого элемента на пути к листу. При отсутствии расщепления это означает простое сложение CF векторов для отражения факта добавления &#039;&#039;Ent&#039;&#039;. Расщепление листа же требует вставки нового нелистьевого элемента в родительский узел для задания только что созданного листа. Если у родителя есть место для этого элемента, то необходимо просто преобразовать CF векторы на всех более высоких уровнях. В общем случае, однако, нам также придётся расщепить родительский узел, и так далее до корня. Если расщеплён корень, то высота дерева увеличивается на единицу.&lt;br /&gt;
&lt;br /&gt;
4) &#039;&#039;Улучшение слияния&#039;&#039;: Расщепление вызвано ограничением на размер узла, который не зависит от кластеризационных свойств данных. Если во входящем потоке присутствуют &amp;quot;искажённые&amp;quot; (из областей с низкой плотностью) данные, это может повлиять на качество кластеризации, а также уменьшить эффективность использования памяти. Дополнительный шаг алгоритма помогает решить эти проблемы: предположим, что произошло расщепление листа, и распространение этого процесса остановилось на некотором нелистьевом узле &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt;, то есть &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; может вместить дополнительный элемент, полученный после расщепления. Теперь мы сканируем узел &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; для нахождения двух наиболее близких элементов. Если это не пара, отвечающая расщеплению, мы пытаемся объединить их и поставить в соответствие два дочерних узла. Если количество элементов в дочерних узлах  больше B, мы снова расщепляем результат объединения.&lt;br /&gt;
В процессе повторного расщепления, в случае, если один источник собирает достаточно элементов для того, чтобы полностью заполнить узел, оставшиеся элементы передаются другом источнику. В итоге, если объединённые элементы помещаются в одном узле, в нём освобождается место для ещё одного элемента. Тем самым увеличивается степень использования свободного пространства и откладывается дальнейшее расщепление. В ином случае мы улучшаем распределение элементов в двух ближайших подкластерах.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро алгоритма заключается в многократном выполнении операции вставки нового элемента в дерево, в процессе чего требуется вычисление следующих величин:&lt;br /&gt;
&lt;br /&gt;
* радиуса &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; или диаметра &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластерного элемента. Выполняется при попытке вставить новый элемент в один из подкластеров листьевого узла дерева.&lt;br /&gt;
&lt;br /&gt;
* расстояния между двумя элементами. Выполняется при поиске ближайшего по отношению к новому элементу подкластера в узле дерева по одной из рассмотренных в разд. 1.2.1 метрик &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Зная характеристики кластерных элементов &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;, в результате алгебраических преобразований можно получить следующие упрощенные формулы вычисления необходимых значений:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\vec{X_0} = \frac{\vec{LS}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{SS - 2\vec{X_0}\vec{LS} + N(\vec{X_0})^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{2(N*SS - (\vec{LS})^2)}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{N_1*SS_2 + N_2*SS_1 - 2\vec{LS_1}\vec{LS_2}}{N_1*N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{2((N_1+N_2)(SS_1+SS_2)-(\vec{LS_1}+\vec{LS_2})^2)}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Реализация алгоритма BIRCH состояит из следующих четырёх фаз:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 1&#039;&#039;&#039;. Главной задачей фазы 1 является сканирование всех данных и построение в памяти исходного CF дерева, используя заданное количество памяти. Это дерево стремится отразить информацию о кластеризации данных настолько хорошо, насколько это позволяют ограничения по памяти. При этом плотно распределённые данные группируются в подкластеры, а более разрозненные данные удаляются. После завершения фазы 1 вспомогательные вычисления в дальнейших фазах будут:&lt;br /&gt;
&lt;br /&gt;
1) быстрее, потому что (а) больше не нужны операции ввода-вывода, (b) проблема кластеризации начальных данных упрощается до проблемы кластеризации подкластеров в листьях;&lt;br /&gt;
&lt;br /&gt;
2) точнее, потому что (а) большинство данных с низкой плотностью удалены, (b) оставшиеся данные распределены оптимально (в соответствии с доступным количеством памяти);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 2&#039;&#039;&#039;. Данная фаза является опциональной. Известно, что существующие методы глобальной кластеризации, используемые в рамках фазы 3, имеют различные диапазоны входных значений, при которых их реализация наиболее эффективна. Поэтому потенциально существует пробел между размером фазы 1 и входными значениями фазы 3. И фаза 2 как раз является недостающим связующим звеном: так же как и фаза 1, она сканирует листьевые элементы начального CF дерева для того, чтобы построить меньшее дерево, удаляя ещё больше элементов с низкой плотностью и группируя переполненные подкластеры в большие кластеры.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 3&#039;&#039;&#039;. В данной фазе для листьевых элементов применяется (любой подходящий) алгоритм глобальной кластеризации. Существующие алгоритмы кластеризации наборов точек могут также работать с наборами подкластеров, каждый из которых представлен своим CF вектором. Зная CF вектор, можно вычислить центроид и в дальнейшем заменить всю информацию о кластере этим значением (этого достаточно для вычисления большинства необходимых метрик). После фазы 3 мы получаем набор кластеров, который отражает основные характеристики распределяемых данных.&lt;br /&gt;
Однако, всё ещё могут оставаться некоторые неточности, для устранения которых существует фаза 4.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 4&#039;&#039;&#039;. Данная фаза является опциональной и влечёт за собой затраты на дополнительное сканирование данных для корректировки неточностей и дальнейшего улучшения кластеризации. Фаза 4 использует центроиды кластеров, полученные в фазе 3 для как основы и перераспределяет точки входных данных в ближайшие для них основы для получения нового списка кластеров. Фаза 4, если это необходимо пользователю, может быть расширена дополнительными проходами для уверенности в том, что результат приближается к оптимальному.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Последовательную реализацию основных операций алгоритма BIRCH можно продемонстрировать на примере следующего фрагмента кода на языке C++:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot;&amp;gt;&lt;br /&gt;
void CF_Node::insert(const CF_Cluster &amp;amp;entry)&lt;br /&gt;
{&lt;br /&gt;
    //Находим ближайший к новому элементу подкластер в узле&lt;br /&gt;
    СF_Vector_it closest = entry.findClosest(subclusters);&lt;br /&gt;
    //Если узел пустой, добавляем в него новый подкластер&lt;br /&gt;
    if (closest == subclusters.end()) {&lt;br /&gt;
        subclusters.push_back(entry);&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    closest-&amp;gt;add(entry);&lt;br /&gt;
    //Если узел является листьевым, и ближайший подкластер не может вместить&lt;br /&gt;
    //новый элемент, добавляем в узел новый подкластер&lt;br /&gt;
    if (leaf) {&lt;br /&gt;
        if (closest-&amp;gt;D &amp;gt; threshold) {&lt;br /&gt;
            closest-&amp;gt;remove(entry);&lt;br /&gt;
            subclusters.push_back(entry);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else {&lt;br /&gt;
        CF_Node *node = closest-&amp;gt;child;&lt;br /&gt;
        node-&amp;gt;insert(entry);&lt;br /&gt;
        //Если при добавлении нового элемента в дочерний узел тот переполнился,&lt;br /&gt;
        //расщепляем его        &lt;br /&gt;
        if (node-&amp;gt;getSubclusters().size() &amp;gt; bFactor) {&lt;br /&gt;
            CF_Vector newClusters = node-&amp;gt;splitNode();&lt;br /&gt;
            delete node;&lt;br /&gt;
            subclusters.erase(closest);&lt;br /&gt;
            subclusters.insert(subclusters.end(), newClusters.begin(), newClusters.end());&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    //Если узел является корневым и он переполнен, расщепляем его&lt;br /&gt;
    if (root &amp;amp;&amp;amp; subclusters.size() &amp;gt; bFactor) {&lt;br /&gt;
        subclusters = splitNode();&lt;br /&gt;
        leaf = false;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
CF_Vector CF_Node::splitNode()&lt;br /&gt;
{&lt;br /&gt;
    if (subclusters.size() &amp;lt; 2)&lt;br /&gt;
        return (root) ? subclusters : CF_Vector{CF_Cluster(this)};&lt;br /&gt;
    //Находим пару наиболее удаленных друг от друга подкластеров&lt;br /&gt;
    CF_Vector_it pole1, pole2;&lt;br /&gt;
    data_t longestDist = 0.0;&lt;br /&gt;
    for (auto lhs = subclusters.begin(); lhs != subclusters.end() - 1; ++lhs) {&lt;br /&gt;
        for (auto rhs = lhs + 1; rhs != subclusters.end(); ++rhs) {&lt;br /&gt;
            auto distance = getDistance(*lhs, *rhs);&lt;br /&gt;
            if (distance &amp;gt; longestDist) {&lt;br /&gt;
                longestDist = distance;&lt;br /&gt;
                pole1 = lhs;&lt;br /&gt;
                pole2 = rhs;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    //Разделяем множество всех подкластеров узла на две части&lt;br /&gt;
    CF_Vector subclusters1, subclusters2;&lt;br /&gt;
    for (auto it = subclusters.begin(); it != subclusters.end(); ++it) {&lt;br /&gt;
        if (getDistance(*it, *pole1) &amp;lt; getDistance(*it, *pole2))&lt;br /&gt;
            subclusters1.push_back(*it);&lt;br /&gt;
        else&lt;br /&gt;
            subclusters2.push_back(*it);&lt;br /&gt;
    }&lt;br /&gt;
    //Создаем два новых узла&lt;br /&gt;
    CF_Node *node1 = new CF_Node(threshold, bFactor, count, leaf, subclusters1),&lt;br /&gt;
            *node2 = new CF_Node(threshold, bFactor, count, leaf, subclusters2);&lt;br /&gt;
    //Связываем листья&lt;br /&gt;
    if (leaf) {&lt;br /&gt;
        if (prevLeaf) {&lt;br /&gt;
            node1-&amp;gt;setPrevLeaf(prevLeaf);&lt;br /&gt;
            prevLeaf-&amp;gt;setNextLeaf(node1);&lt;br /&gt;
        }&lt;br /&gt;
        if (nextLeaf) {&lt;br /&gt;
            node2-&amp;gt;setNextLeaf(nextLeaf);&lt;br /&gt;
            nextLeaf-&amp;gt;setPrevLeaf(node2);&lt;br /&gt;
        }&lt;br /&gt;
        node1-&amp;gt;setNextLeaf(node2);&lt;br /&gt;
        node2-&amp;gt;setPrevLeaf(node1);&lt;br /&gt;
    }&lt;br /&gt;
    CF_Cluster cluster1(node1), cluster2(node2);&lt;br /&gt;
    return CF_Vector{cluster1, cluster2};&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Для начала проанализируем вычислительную сложность фазы 1.&lt;br /&gt;
Максимальный размер дерева &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt; - ограничение по памяти на размер узла, а &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - общий объем памяти. Для того чтобы вставить элемент, мы должны пройти путь от корня до листа (это около &amp;lt;math&amp;gt;1+log_B\frac{M}{P}&amp;lt;/math&amp;gt; узлов). В каждом узле в поисках &amp;quot;ближайшего&amp;quot; нам необходимо просмотреть B элементов; сложность для каждого элемента пропорциональна размерности &#039;&#039;d&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Поэтому сложность вставки всех входных точек &amp;lt;math&amp;gt;O(d \cdot N \cdot B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В случае, когда необходимо перестроить дерево, предположим, что ES - это размер CF элемента. Существует максимум &amp;lt;math&amp;gt;\frac{M}{ES}&amp;lt;/math&amp;gt; листьевых элементов для вставки, поэтому сложность повторной вставки листьевых элементов &amp;lt;math&amp;gt;O(d \cdot \frac{M}{ES} \cdot B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Количество итераций перестройки дерева зависит от пороговой величины. На самом деле, это около &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; (двоичное основание появилось из-за того, что мы не можем провести оценку более чем в 2 раза отличающуюся от текущего размера). &amp;lt;math&amp;gt;N_0&amp;lt;/math&amp;gt; - это число входных точек, загруженных в память с пороговым ограничением &amp;lt;math&amp;gt;T_0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Соответственно, итоговая сложность фазы 1 &amp;lt;math&amp;gt;O(d \cdot N \cdot B(1+log_B\frac{M}{P})+log_2\frac{N}{N_0} \cdot d \cdot \frac{M}{ES} \cdot B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Анализ фазы 2 проводится аналогично.&lt;br /&gt;
&lt;br /&gt;
Что касается операций ввода-вывода, то в фазе 1 данные сканируются один раз, а в фазе 2 не сканируются вовсе.&lt;br /&gt;
Некоторое количество вычислений связано с удалением точек из областей с низкой плотностью.&lt;br /&gt;
Если количество доступной для этой операции памяти не больше &#039;&#039;M&#039;&#039; и проведено порядка &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; перестроек дерева, то сложность ввода-вывода для фазы 1 существенно не отличается от сложности чтения из файла. Основываясь рассуждениях выше, сложность фаз 1 и 2 будет линейно увеличиваться с ростом N.&lt;br /&gt;
&lt;br /&gt;
В фазе 3 нет операций ввода-вывода. Её сложность ограничена константой, которая зависит от максимального размера входных данных, и варианта выбранного алгоритма для кластеризации. &lt;br /&gt;
&lt;br /&gt;
Фаза 4 снова сканирует данные и записывает каждую точку в подходящий кластер; время работы пропорционально &amp;lt;math&amp;gt;N \cdot K&amp;lt;/math&amp;gt;.   &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
=== Вычисление расстояния ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2=\frac{N_1\cdot SS_2+N_2\cdot SS_1-2 \cdot \vec{LS_1}\cdot \vec{LS_2}}{N_1\cdot N_2}&amp;lt;/math&amp;gt;, где&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF_1=[N_1,\vec{LS_1},SS_1]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF_2=[N_2,\vec{LS_2},SS_2]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:ZgYL51QJsQk.jpg|600px|thumb|center]]&lt;br /&gt;
&lt;br /&gt;
=== Поиск ближайшего подкластера ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;E&amp;lt;/math&amp;gt; - новый элемент&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF_i, i = 1,...,B&amp;lt;/math&amp;gt; - подкластеры узла&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - операция min&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\rho&amp;lt;/math&amp;gt; - нахождение расстояния&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:PFA16KHUQ3I.jpg|600px|thumb|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Скалярное произведение ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;s = \vec{x}\cdot\vec{y}=\sum_{i=1}^d x_i\cdot y_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Xb7FYXVMPpQ.jpg|600px|thumb|center]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельно могут быть выполнены следующие шаги алгоритма:&lt;br /&gt;
* Нахождение ближайшего к новому элементу подкластера в узле при выполнении операции вставки. Это возможно за счет того, что расстояние между парами элементов может быть вычислено независимо друг от друга. Сложность &lt;br /&gt;
* Вычисление величин &amp;lt;math&amp;gt;\vec{LS},\vec{X0}, R, D, D_0-D_4&amp;lt;/math&amp;gt;, в процессе чего выполняются операции сложения и скалярного произведения векторов.&lt;br /&gt;
&lt;br /&gt;
Другим способом параллелизации алгоритма может служить создание и заполнение сразу множества кластерных деревьев, между которыми будут распределены входные данные. Множество всех подкластеров листьевых узлов полученных таким образом деревьев может быть подвергнуто глобальной кластеризации с помощью какого-либо из известных параллельных алгоритмов, например, k-средних&amp;lt;ref&amp;gt;[http://people.du.ac.in/~ngupta/Publications/PBIRCH%20A%20Sacalabel%20Paralllel%20Clustering.pdf A Garg, N Gupta PBIRCH: A Scalable Parallel Clustering algorithm for Incremental Data]&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;
* Набор из &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек &amp;lt;math&amp;gt;\{X_i\}, i=1,...,N&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Кластерное дерево с не более чем &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt; узлами.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Достоинства алгоритма ===&lt;br /&gt;
По сравнению с предыдущими методами BIRCH обладает следующими достоинствами:&lt;br /&gt;
&lt;br /&gt;
1. BIRCH является локальным алгоритмом, то есть каждое решение о каждом элементе кластера принимается без повторного сканирования данных или уже существующих кластеров. Используются только метрики, отражающие близость элементов друг к другу.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH использует факт неравномерного распределения данных в пространстве и поэтому не все данные рассматриваются как одинаково важные для построения кластера. Области с большой плотностью обрабатываются как единый кластер. Данные в более разреженных областях могут удаляться (опционально).&lt;br /&gt;
&lt;br /&gt;
3. BIRCH использует всю доступную память для получения наилучших из возможных подкластеров, в то же время минимизируя затраты на операции ввода/вывода. Оптимизация процесса кластеризации достигается за счет использования взвешенно-сбалансированного дерева. При этом время исполнения линейно.&lt;br /&gt;
&lt;br /&gt;
4. BIRCH не требует всего набора данных заранее (при этом просматривает его всего один раз).&lt;br /&gt;
&lt;br /&gt;
=== Недостатки алгоритма ===&lt;br /&gt;
&lt;br /&gt;
1. Алгоритм позволяет работать только с числовыми данными.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH хорошо выделяет только кластеры сферической формы.&lt;br /&gt;
&lt;br /&gt;
3. Существует необходимость в задании пороговых значений.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
В составе пакетов и библиотек:&lt;br /&gt;
* [http://scikit-learn.org/stable/modules/generated/sklearn.cluster.Birch.html scikit-learn]&lt;br /&gt;
* [http://cucis.ece.northwestern.edu/projects/DMS/MineBench.html NU-MineBench]&lt;br /&gt;
Пользовательские реализации:&lt;br /&gt;
* [https://code.google.com/archive/p/jbirch/ JBIRCH]&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Светлана Морозова</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13846</id>
		<title>Участник:Smirnov.maxim/BIRCH</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13846"/>
		<updated>2016-10-26T07:41:19Z</updated>

		<summary type="html">&lt;p&gt;Светлана Морозова: /* Вычисление расстояния */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Авторы: [[Участник:Светлана Морозова|Морозова Светлана]], [[Участник:Smirnov.maxim|Смирнов Максим]].&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Нахождение полезных для анализа закономерностей в больших объёмах данных с недавних пор вызывает значительный интерес. В связи с этим ввелось и стало активно развиваться такое понятие как &#039;&#039;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7 кластеризация]&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Ранние работы и алгоритмы, разработанные в этой области, не уделяли достаточного внимания анализу очень больших наборов данных или минимизации издержек на процессы ввода-вывода.&lt;br /&gt;
Решением этих проблем стал алгоритм, известный как BIRCH.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIRCH&#039;&#039;&#039;&amp;lt;ref&amp;gt;[http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf Нейский И.М. Классификация и сравнение методов кластеризации]&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;[http://www.cs.sfu.ca/CourseCentral/459/han/papers/zhang96.pdf T Zhang, R Ramakrishnan, M Livny. BIRCH: An Efficient Data Clustering Method for Very Large Databases]&amp;lt;/ref&amp;gt; (balanced iterative reducing and clustering using hierarchies)- алгоритм, применяемый в области [https://ru.wikipedia.org/wiki/Data_mining Data mining] и использующий принципы [https://ru.wikipedia.org/wiki/%D0%98%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F иерархической кластеризации].&lt;br /&gt;
&lt;br /&gt;
Если имеется очень большой набор данных, то в пространстве он распределен, как правило, неравномерно. Кластерный анализ определяет места наибольшего и наименьшего скоплений, чтобы таким образом понять всю картину целиком. Кроме того, полученные кластеры визуализируются гораздо нагляднее, чем начальные &amp;quot;сырые&amp;quot; данные.&lt;br /&gt;
Задачей алгоритмов кластеризации является не только простое разбиение данных на кластеры, но и работа в рамках ограниченного объёма доступной памяти (как правило, её объём гораздо меньше, чем размер исходного набора данных) и минимизация времени, требуемого на операции ввода-вывода.&lt;br /&gt;
&lt;br /&gt;
Для наилучшего решения этих проблем BIRCH распределяет входящие данные по кластерам динамически. Для эффективной кластеризации алгоритму требуется всего одно сканирование данных (т.е. с увеличением количества данных сложность увеличивается линейно). А при помощи одной (или более) дополнительных итераций можно и далее улучшать эффективность. BIRCH также является первым алгоритмом, предложенным для эффективного управления &amp;quot;шумами&amp;quot; (данными, которые не вписываются в общее представление модели).&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Теоретическая основа ===&lt;br /&gt;
&lt;br /&gt;
Пусть в кластере имеются &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}, i=1,2,...,N&amp;lt;/math&amp;gt;.&lt;br /&gt;
Тогда &#039;&#039;&#039;центроид&#039;&#039;&#039; &amp;lt;math&amp;gt;{\vec{{X_0}}}&amp;lt;/math&amp;gt;, &#039;&#039;&#039;радиус&#039;&#039;&#039; &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &#039;&#039;&#039;диаметр&#039;&#039;&#039; &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластера определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;{\vec{X_0}}=\frac{\sum_{i=1}^N\vec{X_i}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{\sum_{i=1}^N{(\vec{X_i} - \vec{X_0})}^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{\sum_{i=1}^N\sum_{j=1}^N{(\vec{X_i} - \vec{X_j})}^2}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; - это среднее расстояние от каждой точки до центроида. &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; - это среднее расстояние между парами в кластере. Данные величины являются альтернативными метриками плотности кластера относительно центроида.&lt;br /&gt;
&lt;br /&gt;
Для измерения близости друг к другу двух кластеров вводятся следующие метрики:&lt;br /&gt;
&lt;br /&gt;
пусть даны центроиды двух кластеров &amp;lt;math&amp;gt;\vec{X_{01}}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\vec{X_{02}}&amp;lt;/math&amp;gt;.&lt;br /&gt;
Евклидова метрика &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt; и метрика Манхэттена &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt; между двумя кластерами определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_0 = ((\vec{X_{01}}-\vec{X_{02}})^2)^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_1 = |\vec{X_{01}}-\vec{X_{02}}| = \sum_{i=1}^d |{\vec{X_{01}}}^{(i)}-{\vec{X_{02}}}^{(i)}| &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть имеются два кластера, содержащих соответственно  &amp;lt;math&amp;gt;N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;N_2&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i= 1,2, ...,N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\{\vec{X_j}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j= N_1+1,N_1+2, ...,N_1+N_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Среднее расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &#039;&#039;&#039;среднее внутрикластерное расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &#039;&#039;&#039;дисперсия&#039;&#039;&#039; &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; для двух кластеров определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{\sum_{i=1}^{N_1}\sum_{j=N_1+1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{N_1N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{\sum_{i=1}^{N_1+N_2}\sum_{j=1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_4 = \sum_{k=1}^{N_1+N_2}(\vec{X_k} - \frac{\sum_{i=1}^{N_1+N_2}\vec{X_i}}{N_1+N_2})^2 - \sum_{i=1}^{N_1}(\vec{X_i} - \frac{\sum_{i=1}^{N_1}\vec{X_i}}{N_1})^2 - \sum_{j=N_1+1}^{N_1+N_2}(\vec{X_j} - \frac{\sum_{i=N_1+1}^{N_1+N_2}\vec{X_i}}{N_2})^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Таким образом, величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; относятся к отдельным кластерам, а &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; - к объединению двух кластеров.&lt;br /&gt;
&lt;br /&gt;
=== Кластерный элемент и кластерное дерево ===&lt;br /&gt;
&lt;br /&gt;
В основе концепции алгоритма BIRCH лежат понятия &#039;&#039;&#039;кластерного элемента&#039;&#039;&#039; и &#039;&#039;&#039;кластерного дерева (CF Tree)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====Кластерный элемент ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; Пусть в кластере содержатся  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности  &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;:&amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;i=1,2,...,N&amp;lt;/math&amp;gt;. &lt;br /&gt;
&#039;&#039;&#039;Кластерный элемент (CF)&#039;&#039;&#039; - тройка чисел, характеризующая информацию о кластере: &lt;br /&gt;
&amp;lt;math&amp;gt;CF = (N, \vec{LS}, SS)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - количество элементов входных данных, содержащихся в кластере, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; - линейная сумма входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}\vec{X_i}&amp;lt;/math&amp;gt;), &amp;lt;math&amp;gt;SS&amp;lt;/math&amp;gt; - сумма квадратов входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}{\vec{X_i}}^2&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Теорема&#039;&#039;&#039; Пусть &amp;lt;math&amp;gt;CF_1 = (N_1, \vec{LS_1}, SS_1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;CF_2 = (N_1, \vec{LS_2}, SS_2)&amp;lt;/math&amp;gt; - CF векторы двух непересекающихся кластеров. Тогда при их объединении образуется кластер со следующим CF вектором: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF = CF_1 + CF_2 = (N_1+N_2, \vec{LS_1}+\vec{LS_2}, SS_1+SS_2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Из указанных выше определения и теоремы вытекает тот факт, что при объединении кластеров их CF вектор может вычисляться инкрементно и точно. &lt;br /&gt;
Легко показать, что вычислить величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;, как и обычные метрики, также не составит труда.&lt;br /&gt;
&lt;br /&gt;
Таким образом, в данном случае информацией о кластере является не весь набор точек, а вектор CF. Хранение одного только вектора может показаться неэффективным, но этого вполне достаточно для оперирования всеми необходимыми метриками, на основе которых принимаются решения в алгоритме BIRCH.&lt;br /&gt;
&lt;br /&gt;
==== Кластерное дерево ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; &#039;&#039;&#039;Кластерное дерево (CF Tree)&#039;&#039;&#039; - это взвешенно сбалансированное дерево с двумя параметрами: &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - коэффициент разветвления, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - пороговая величина.&lt;br /&gt;
&lt;br /&gt;
Каждый нелистьевой узел дерева имеет не более чем &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; вхождений узлов следующей формы: &amp;lt;math&amp;gt;[CF_i,child_i]&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i=1,2,...,B&amp;lt;/math&amp;gt;, &#039;&#039;child&#039;&#039; - указатель на i-й дочерний узел, &amp;lt;math&amp;gt;CF_i&amp;lt;/math&amp;gt; - CF вектор соответствующего подкластера.&lt;br /&gt;
&lt;br /&gt;
Каждый листьевой узел имеет ссылку на два соседних узла (&#039;&#039;prev&#039;&#039; и &#039;&#039;next&#039;&#039;) для того, чтобы связать все узлы для эффективного сканирования.&lt;br /&gt;
Все листьевые узлы должны удовлетворять пороговому ограничению &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, т.е. диаметр (радиус) не должен превосходить &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;.&lt;br /&gt;
В процессе вставки новых данных CF дерево строится динамически. Оно использует вставку данных для кластеризации точно также как &amp;lt;math&amp;gt;B+&amp;lt;/math&amp;gt; [https://ru.wikipedia.org/wiki/B%2B-%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE дерево] использует её для поиска.&lt;br /&gt;
CF дерево очень компактно, поскольку каждый листьевой узел - это не просто точка, а подкластер (который объединяет множество точек с учётом ограничения &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Операция вставки в &#039;&#039;&#039;CF&#039;&#039;&#039; дерево ====&lt;br /&gt;
&lt;br /&gt;
Опишем алгоритм вставки элемнта &amp;lt;math&amp;gt;Ent&amp;lt;/math&amp;gt; в CF дерево:&lt;br /&gt;
&lt;br /&gt;
1) &#039;&#039;Определение подходящего листа&#039;&#039;: Начиная с корня, алгоритм рекурсивно спускается по CF дереву, выбирая &#039;&#039;&#039;ближайший&#039;&#039;&#039; дочерний узел в соответствии с выбранной метрикой &amp;lt;math&amp;gt;D0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D4&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &#039;&#039;Преобразование листа&#039;&#039;: Когда алгоритм доходит до листа, он находит ближайшую листьевой элемент, скажем, &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;, а затем проверяет, можно ли добавить &#039;&#039;Ent&#039;&#039; к &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt; без нарушения порогового условия. Если да, то с учётом этого изменяется CF вектор для &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;; если нет, то &#039;&#039;Ent&#039;&#039; становится новым элементом листа. Если в листе для этого достаточно места, то шаг окончен, иначе он должен &amp;quot;расщепиться&amp;quot;. Расщепление узла производится при помощи выбора за основу наиболее удалённой друг от друга пары элементов и перераспределение оставшихся элементов в соответствии с выбранным критерием близости.&lt;br /&gt;
&lt;br /&gt;
3) &#039;&#039;Преобразование пути к листу&#039;&#039;: После вставки &#039;&#039;Ent&#039;&#039; в лист мы должны обновить информацию о CF для каждого нелистьевого элемента на пути к листу. При отсутствии расщепления это означает простое сложение CF векторов для отражения факта добавления &#039;&#039;Ent&#039;&#039;. Расщепление листа же требует вставки нового нелистьевого элемента в родительский узел для задания только что созданного листа. Если у родителя есть место для этого элемента, то необходимо просто преобразовать CF векторы на всех более высоких уровнях. В общем случае, однако, нам также придётся расщепить родительский узел, и так далее до корня. Если расщеплён корень, то высота дерева увеличивается на единицу.&lt;br /&gt;
&lt;br /&gt;
4) &#039;&#039;Улучшение слияния&#039;&#039;: Расщепление вызвано ограничением на размер узла, который не зависит от кластеризационных свойств данных. Если во входящем потоке присутствуют &amp;quot;искажённые&amp;quot; (из областей с низкой плотностью) данные, это может повлиять на качество кластеризации, а также уменьшить эффективность использования памяти. Дополнительный шаг алгоритма помогает решить эти проблемы: предположим, что произошло расщепление листа, и распространение этого процесса остановилось на некотором нелистьевом узле &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt;, то есть &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; может вместить дополнительный элемент, полученный после расщепления. Теперь мы сканируем узел &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; для нахождения двух наиболее близких элементов. Если это не пара, отвечающая расщеплению, мы пытаемся объединить их и поставить в соответствие два дочерних узла. Если количество элементов в дочерних узлах  больше B, мы снова расщепляем результат объединения.&lt;br /&gt;
В процессе повторного расщепления, в случае, если один источник собирает достаточно элементов для того, чтобы полностью заполнить узел, оставшиеся элементы передаются другом источнику. В итоге, если объединённые элементы помещаются в одном узле, в нём освобождается место для ещё одного элемента. Тем самым увеличивается степень использования свободного пространства и откладывается дальнейшее расщепление. В ином случае мы улучшаем распределение элементов в двух ближайших подкластерах.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро алгоритма заключается в многократном выполнении операции вставки нового элемента в дерево, в процессе чего требуется вычисление следующих величин:&lt;br /&gt;
&lt;br /&gt;
* радиуса &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; или диаметра &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластерного элемента. Выполняется при попытке вставить новый элемент в один из подкластеров листьевого узла дерева.&lt;br /&gt;
&lt;br /&gt;
* расстояния между двумя элементами. Выполняется при поиске ближайшего по отношению к новому элементу подкластера в узле дерева по одной из рассмотренных в разд. 1.2.1 метрик &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Зная характеристики кластерных элементов &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;, в результате алгебраических преобразований можно получить следующие упрощенные формулы вычисления необходимых значений:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\vec{X_0} = \frac{\vec{LS}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{SS - 2\vec{X_0}\vec{LS} + N(\vec{X_0})^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{2(N*SS - (\vec{LS})^2)}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{N_1*SS_2 + N_2*SS_1 - 2\vec{LS_1}\vec{LS_2}}{N_1*N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{2((N_1+N_2)(SS_1+SS_2)-(\vec{LS_1}+\vec{LS_2})^2)}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Реализация алгоритма BIRCH состояит из следующих четырёх фаз:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 1&#039;&#039;&#039;. Главной задачей фазы 1 является сканирование всех данных и построение в памяти исходного CF дерева, используя заданное количество памяти. Это дерево стремится отразить информацию о кластеризации данных настолько хорошо, насколько это позволяют ограничения по памяти. При этом плотно распределённые данные группируются в подкластеры, а более разрозненные данные удаляются. После завершения фазы 1 вспомогательные вычисления в дальнейших фазах будут:&lt;br /&gt;
&lt;br /&gt;
1) быстрее, потому что (а) больше не нужны операции ввода-вывода, (b) проблема кластеризации начальных данных упрощается до проблемы кластеризации подкластеров в листьях;&lt;br /&gt;
&lt;br /&gt;
2) точнее, потому что (а) большинство данных с низкой плотностью удалены, (b) оставшиеся данные распределены оптимально (в соответствии с доступным количеством памяти);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 2&#039;&#039;&#039;. Данная фаза является опциональной. Известно, что существующие методы глобальной кластеризации, используемые в рамках фазы 3, имеют различные диапазоны входных значений, при которых их реализация наиболее эффективна. Поэтому потенциально существует пробел между размером фазы 1 и входными значениями фазы 3. И фаза 2 как раз является недостающим связующим звеном: так же как и фаза 1, она сканирует листьевые элементы начального CF дерева для того, чтобы построить меньшее дерево, удаляя ещё больше элементов с низкой плотностью и группируя переполненные подкластеры в большие кластеры.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 3&#039;&#039;&#039;. В данной фазе для листьевых элементов применяется (любой подходящий) алгоритм глобальной кластеризации. Существующие алгоритмы кластеризации наборов точек могут также работать с наборами подкластеров, каждый из которых представлен своим CF вектором. Зная CF вектор, можно вычислить центроид и в дальнейшем заменить всю информацию о кластере этим значением (этого достаточно для вычисления большинства необходимых метрик). После фазы 3 мы получаем набор кластеров, который отражает основные характеристики распределяемых данных.&lt;br /&gt;
Однако, всё ещё могут оставаться некоторые неточности, для устранения которых существует фаза 4.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 4&#039;&#039;&#039;. Данная фаза является опциональной и влечёт за собой затраты на дополнительное сканирование данных для корректировки неточностей и дальнейшего улучшения кластеризации. Фаза 4 использует центроиды кластеров, полученные в фазе 3 для как основы и перераспределяет точки входных данных в ближайшие для них основы для получения нового списка кластеров. Фаза 4, если это необходимо пользователю, может быть расширена дополнительными проходами для уверенности в том, что результат приближается к оптимальному.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Последовательную реализацию основных операций алгоритма BIRCH можно продемонстрировать на примере следующего фрагмента кода на языке C++:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot;&amp;gt;&lt;br /&gt;
void CF_Node::insert(const CF_Cluster &amp;amp;entry)&lt;br /&gt;
{&lt;br /&gt;
    //Находим ближайший к новому элементу подкластер в узле&lt;br /&gt;
    СF_Vector_it closest = entry.findClosest(subclusters);&lt;br /&gt;
    //Если узел пустой, добавляем в него новый подкластер&lt;br /&gt;
    if (closest == subclusters.end()) {&lt;br /&gt;
        subclusters.push_back(entry);&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    closest-&amp;gt;add(entry);&lt;br /&gt;
    //Если узел является листьевым, и ближайший подкластер не может вместить&lt;br /&gt;
    //новый элемент, добавляем в узел новый подкластер&lt;br /&gt;
    if (leaf) {&lt;br /&gt;
        if (closest-&amp;gt;D &amp;gt; threshold) {&lt;br /&gt;
            closest-&amp;gt;remove(entry);&lt;br /&gt;
            subclusters.push_back(entry);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else {&lt;br /&gt;
        CF_Node *node = closest-&amp;gt;child;&lt;br /&gt;
        node-&amp;gt;insert(entry);&lt;br /&gt;
        //Если при добавлении нового элемента в дочерний узел тот переполнился,&lt;br /&gt;
        //расщепляем его        &lt;br /&gt;
        if (node-&amp;gt;getSubclusters().size() &amp;gt; bFactor) {&lt;br /&gt;
            CF_Vector newClusters = node-&amp;gt;splitNode();&lt;br /&gt;
            delete node;&lt;br /&gt;
            subclusters.erase(closest);&lt;br /&gt;
            subclusters.insert(subclusters.end(), newClusters.begin(), newClusters.end());&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    //Если узел является корневым и он переполнен, расщепляем его&lt;br /&gt;
    if (root &amp;amp;&amp;amp; subclusters.size() &amp;gt; bFactor) {&lt;br /&gt;
        subclusters = splitNode();&lt;br /&gt;
        leaf = false;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
CF_Vector CF_Node::splitNode()&lt;br /&gt;
{&lt;br /&gt;
    if (subclusters.size() &amp;lt; 2)&lt;br /&gt;
        return (root) ? subclusters : CF_Vector{CF_Cluster(this)};&lt;br /&gt;
    //Находим пару наиболее удаленных друг от друга подкластеров&lt;br /&gt;
    CF_Vector_it pole1, pole2;&lt;br /&gt;
    data_t longestDist = 0.0;&lt;br /&gt;
    for (auto lhs = subclusters.begin(); lhs != subclusters.end() - 1; ++lhs) {&lt;br /&gt;
        for (auto rhs = lhs + 1; rhs != subclusters.end(); ++rhs) {&lt;br /&gt;
            auto distance = getDistance(*lhs, *rhs);&lt;br /&gt;
            if (distance &amp;gt; longestDist) {&lt;br /&gt;
                longestDist = distance;&lt;br /&gt;
                pole1 = lhs;&lt;br /&gt;
                pole2 = rhs;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    //Разделяем множество всех подкластеров узла на две части&lt;br /&gt;
    CF_Vector subclusters1, subclusters2;&lt;br /&gt;
    for (auto it = subclusters.begin(); it != subclusters.end(); ++it) {&lt;br /&gt;
        if (getDistance(*it, *pole1) &amp;lt; getDistance(*it, *pole2))&lt;br /&gt;
            subclusters1.push_back(*it);&lt;br /&gt;
        else&lt;br /&gt;
            subclusters2.push_back(*it);&lt;br /&gt;
    }&lt;br /&gt;
    //Создаем два новых узла&lt;br /&gt;
    CF_Node *node1 = new CF_Node(threshold, bFactor, count, leaf, subclusters1),&lt;br /&gt;
            *node2 = new CF_Node(threshold, bFactor, count, leaf, subclusters2);&lt;br /&gt;
    //Связываем листья&lt;br /&gt;
    if (leaf) {&lt;br /&gt;
        if (prevLeaf) {&lt;br /&gt;
            node1-&amp;gt;setPrevLeaf(prevLeaf);&lt;br /&gt;
            prevLeaf-&amp;gt;setNextLeaf(node1);&lt;br /&gt;
        }&lt;br /&gt;
        if (nextLeaf) {&lt;br /&gt;
            node2-&amp;gt;setNextLeaf(nextLeaf);&lt;br /&gt;
            nextLeaf-&amp;gt;setPrevLeaf(node2);&lt;br /&gt;
        }&lt;br /&gt;
        node1-&amp;gt;setNextLeaf(node2);&lt;br /&gt;
        node2-&amp;gt;setPrevLeaf(node1);&lt;br /&gt;
    }&lt;br /&gt;
    CF_Cluster cluster1(node1), cluster2(node2);&lt;br /&gt;
    return CF_Vector{cluster1, cluster2};&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Для начала проанализируем вычислительную сложность фазы 1.&lt;br /&gt;
Максимальный размер дерева &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt; - ограничение по памяти на размер узла, а &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - общий объем памяти. Для того чтобы вставить элемент, мы должны пройти путь от корня до листа (это около &amp;lt;math&amp;gt;1+log_B\frac{M}{P}&amp;lt;/math&amp;gt; узлов). В каждом узле в поисках &amp;quot;ближайшего&amp;quot; нам необходимо просмотреть B элементов; сложность для каждого элемента пропорциональна размерности &#039;&#039;d&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Поэтому сложность вставки всех входных точек &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В случае, когда необходимо перестроить дерево, предположим, что ES - это размер CF элемента. Существует максимум &amp;lt;math&amp;gt;\frac{M}{ES}&amp;lt;/math&amp;gt; листьевых элементов для вставки, поэтому сложность повторной вставки листьевых элементов &amp;lt;math&amp;gt;O(d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Количество итераций перестройки дерева зависит от пороговой величины. На самом деле, это около &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; (двоичное основание появилось из-за того, что мы не можем провести оценку более чем в 2 раза отличающуюся от текущего размера). &amp;lt;math&amp;gt;N_0&amp;lt;/math&amp;gt; - это число входных точек, загруженных в память с пороговым ограничением &amp;lt;math&amp;gt;T_0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Соответственно, итоговая сложность фазы 1 &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P})+log_2\frac{N}{N_0}*d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Анализ фазы 2 проводится аналогично.&lt;br /&gt;
&lt;br /&gt;
Что касается операций ввода-вывода, то в фазе 1 данные сканируются один раз, а в фазе 2 не сканируются вовсе.&lt;br /&gt;
Некоторое количество вычислений связано с удалением точек из областей с низкой плотностью.&lt;br /&gt;
Если количество доступной для этой операции памяти не больше &#039;&#039;M&#039;&#039; и проведено порядка &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; перестроек дерева, то сложность ввода-вывода для фазы 1 существенно не отличается от сложности чтения из файла. Основываясь рассуждениях выше, сложность фаз 1 и 2 будет линейно увеличиваться с ростом N.&lt;br /&gt;
&lt;br /&gt;
В фазе 3 нет операций ввода-вывода. Её сложность ограничена константой, которая зависит от максимального размера входных данных, и варианта выбранного алгоритма для кластеризации. &lt;br /&gt;
&lt;br /&gt;
Фаза 4 снова сканирует данные и записывает каждую точку в подходящий кластер; время работы пропорционально &amp;lt;math&amp;gt;N*K&amp;lt;/math&amp;gt;.   &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
=== Вычисление расстояния ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2=\frac{N_1\cdot SS_2+N_2\cdot SS_1-2 \cdot \vec{LS_1}\cdot \vec{LS_2}}{N_1\cdot N_2}&amp;lt;/math&amp;gt;, где&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF_1=[N_1,\vec{LS_1},SS_1]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF_2=[N_2,\vec{LS_2},SS_2]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:ZgYL51QJsQk.jpg|600px|thumb|center]]&lt;br /&gt;
&lt;br /&gt;
=== Поиск ближайшего подкластера ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;E&amp;lt;/math&amp;gt; - новый элемент&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF_i, i = 1,...,B&amp;lt;/math&amp;gt; - подкластеры узла&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - операция min&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\rho&amp;lt;/math&amp;gt; - нахождение расстояния&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:PFA16KHUQ3I.jpg|600px|thumb|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Скалярное произведение ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;s = \vec{x}\cdot\vec{y}=\sum_{i=1}^d x_i\cdot y_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Xb7FYXVMPpQ.jpg|600px|thumb|center]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельно могут быть выполнены следующие шаги алгоритма:&lt;br /&gt;
* Нахождение ближайшего к новому элементу подкластера в узле при выполнении операции вставки. Это возможно за счет того, что расстояние между парами элементов может быть вычислено независимо друг от друга. Сложность &lt;br /&gt;
* Вычисление величин &amp;lt;math&amp;gt;\vec{LS},\vec{X0}, R, D, D_0-D_4&amp;lt;/math&amp;gt;, в процессе чего выполняются операции сложения и скалярного произведения векторов.&lt;br /&gt;
&lt;br /&gt;
Другим способом параллелизации алгоритма может служить создание и заполнение сразу множества кластерных деревьев, между которыми будут распределены входные данные. Множество всех подкластеров листьевых узлов полученных таким образом деревьев может быть подвергнуто глобальной кластеризации с помощью какого-либо из известных параллельных алгоритмов, например, k-средних&amp;lt;ref&amp;gt;[http://people.du.ac.in/~ngupta/Publications/PBIRCH%20A%20Sacalabel%20Paralllel%20Clustering.pdf A Garg, N Gupta PBIRCH: A Scalable Parallel Clustering algorithm for Incremental Data]&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;
* Набор из &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек &amp;lt;math&amp;gt;\{X_i\}, i=1,...,N&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Кластерное дерево с не более чем &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt; узлами.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Достоинства алгоритма ===&lt;br /&gt;
По сравнению с предыдущими методами BIRCH обладает следующими достоинствами:&lt;br /&gt;
&lt;br /&gt;
1. BIRCH является локальным алгоритмом, то есть каждое решение о каждом элементе кластера принимается без повторного сканирования данных или уже существующих кластеров. Используются только метрики, отражающие близость элементов друг к другу.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH использует факт неравномерного распределения данных в пространстве и поэтому не все данные рассматриваются как одинаково важные для построения кластера. Области с большой плотностью обрабатываются как единый кластер. Данные в более разреженных областях могут удаляться (опционально).&lt;br /&gt;
&lt;br /&gt;
3. BIRCH использует всю доступную память для получения наилучших из возможных подкластеров, в то же время минимизируя затраты на операции ввода/вывода. Оптимизация процесса кластеризации достигается за счет использования взвешенно-сбалансированного дерева. При этом время исполнения линейно.&lt;br /&gt;
&lt;br /&gt;
4. BIRCH не требует всего набора данных заранее (при этом просматривает его всего один раз).&lt;br /&gt;
&lt;br /&gt;
=== Недостатки алгоритма ===&lt;br /&gt;
&lt;br /&gt;
1. Алгоритм позволяет работать только с числовыми данными.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH хорошо выделяет только кластеры сферической формы.&lt;br /&gt;
&lt;br /&gt;
3. Существует необходимость в задании пороговых значений.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
В составе пакетов и библиотек:&lt;br /&gt;
* [http://scikit-learn.org/stable/modules/generated/sklearn.cluster.Birch.html scikit-learn]&lt;br /&gt;
* [http://cucis.ece.northwestern.edu/projects/DMS/MineBench.html NU-MineBench]&lt;br /&gt;
Пользовательские реализации:&lt;br /&gt;
* [https://code.google.com/archive/p/jbirch/ JBIRCH]&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Светлана Морозова</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13845</id>
		<title>Участник:Smirnov.maxim/BIRCH</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13845"/>
		<updated>2016-10-26T07:40:49Z</updated>

		<summary type="html">&lt;p&gt;Светлана Морозова: /* Информационный граф */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Авторы: [[Участник:Светлана Морозова|Морозова Светлана]], [[Участник:Smirnov.maxim|Смирнов Максим]].&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Нахождение полезных для анализа закономерностей в больших объёмах данных с недавних пор вызывает значительный интерес. В связи с этим ввелось и стало активно развиваться такое понятие как &#039;&#039;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7 кластеризация]&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Ранние работы и алгоритмы, разработанные в этой области, не уделяли достаточного внимания анализу очень больших наборов данных или минимизации издержек на процессы ввода-вывода.&lt;br /&gt;
Решением этих проблем стал алгоритм, известный как BIRCH.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIRCH&#039;&#039;&#039;&amp;lt;ref&amp;gt;[http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf Нейский И.М. Классификация и сравнение методов кластеризации]&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;[http://www.cs.sfu.ca/CourseCentral/459/han/papers/zhang96.pdf T Zhang, R Ramakrishnan, M Livny. BIRCH: An Efficient Data Clustering Method for Very Large Databases]&amp;lt;/ref&amp;gt; (balanced iterative reducing and clustering using hierarchies)- алгоритм, применяемый в области [https://ru.wikipedia.org/wiki/Data_mining Data mining] и использующий принципы [https://ru.wikipedia.org/wiki/%D0%98%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F иерархической кластеризации].&lt;br /&gt;
&lt;br /&gt;
Если имеется очень большой набор данных, то в пространстве он распределен, как правило, неравномерно. Кластерный анализ определяет места наибольшего и наименьшего скоплений, чтобы таким образом понять всю картину целиком. Кроме того, полученные кластеры визуализируются гораздо нагляднее, чем начальные &amp;quot;сырые&amp;quot; данные.&lt;br /&gt;
Задачей алгоритмов кластеризации является не только простое разбиение данных на кластеры, но и работа в рамках ограниченного объёма доступной памяти (как правило, её объём гораздо меньше, чем размер исходного набора данных) и минимизация времени, требуемого на операции ввода-вывода.&lt;br /&gt;
&lt;br /&gt;
Для наилучшего решения этих проблем BIRCH распределяет входящие данные по кластерам динамически. Для эффективной кластеризации алгоритму требуется всего одно сканирование данных (т.е. с увеличением количества данных сложность увеличивается линейно). А при помощи одной (или более) дополнительных итераций можно и далее улучшать эффективность. BIRCH также является первым алгоритмом, предложенным для эффективного управления &amp;quot;шумами&amp;quot; (данными, которые не вписываются в общее представление модели).&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Теоретическая основа ===&lt;br /&gt;
&lt;br /&gt;
Пусть в кластере имеются &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}, i=1,2,...,N&amp;lt;/math&amp;gt;.&lt;br /&gt;
Тогда &#039;&#039;&#039;центроид&#039;&#039;&#039; &amp;lt;math&amp;gt;{\vec{{X_0}}}&amp;lt;/math&amp;gt;, &#039;&#039;&#039;радиус&#039;&#039;&#039; &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &#039;&#039;&#039;диаметр&#039;&#039;&#039; &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластера определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;{\vec{X_0}}=\frac{\sum_{i=1}^N\vec{X_i}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{\sum_{i=1}^N{(\vec{X_i} - \vec{X_0})}^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{\sum_{i=1}^N\sum_{j=1}^N{(\vec{X_i} - \vec{X_j})}^2}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; - это среднее расстояние от каждой точки до центроида. &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; - это среднее расстояние между парами в кластере. Данные величины являются альтернативными метриками плотности кластера относительно центроида.&lt;br /&gt;
&lt;br /&gt;
Для измерения близости друг к другу двух кластеров вводятся следующие метрики:&lt;br /&gt;
&lt;br /&gt;
пусть даны центроиды двух кластеров &amp;lt;math&amp;gt;\vec{X_{01}}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\vec{X_{02}}&amp;lt;/math&amp;gt;.&lt;br /&gt;
Евклидова метрика &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt; и метрика Манхэттена &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt; между двумя кластерами определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_0 = ((\vec{X_{01}}-\vec{X_{02}})^2)^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_1 = |\vec{X_{01}}-\vec{X_{02}}| = \sum_{i=1}^d |{\vec{X_{01}}}^{(i)}-{\vec{X_{02}}}^{(i)}| &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть имеются два кластера, содержащих соответственно  &amp;lt;math&amp;gt;N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;N_2&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i= 1,2, ...,N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\{\vec{X_j}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j= N_1+1,N_1+2, ...,N_1+N_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Среднее расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &#039;&#039;&#039;среднее внутрикластерное расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &#039;&#039;&#039;дисперсия&#039;&#039;&#039; &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; для двух кластеров определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{\sum_{i=1}^{N_1}\sum_{j=N_1+1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{N_1N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{\sum_{i=1}^{N_1+N_2}\sum_{j=1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_4 = \sum_{k=1}^{N_1+N_2}(\vec{X_k} - \frac{\sum_{i=1}^{N_1+N_2}\vec{X_i}}{N_1+N_2})^2 - \sum_{i=1}^{N_1}(\vec{X_i} - \frac{\sum_{i=1}^{N_1}\vec{X_i}}{N_1})^2 - \sum_{j=N_1+1}^{N_1+N_2}(\vec{X_j} - \frac{\sum_{i=N_1+1}^{N_1+N_2}\vec{X_i}}{N_2})^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Таким образом, величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; относятся к отдельным кластерам, а &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; - к объединению двух кластеров.&lt;br /&gt;
&lt;br /&gt;
=== Кластерный элемент и кластерное дерево ===&lt;br /&gt;
&lt;br /&gt;
В основе концепции алгоритма BIRCH лежат понятия &#039;&#039;&#039;кластерного элемента&#039;&#039;&#039; и &#039;&#039;&#039;кластерного дерева (CF Tree)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====Кластерный элемент ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; Пусть в кластере содержатся  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности  &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;:&amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;i=1,2,...,N&amp;lt;/math&amp;gt;. &lt;br /&gt;
&#039;&#039;&#039;Кластерный элемент (CF)&#039;&#039;&#039; - тройка чисел, характеризующая информацию о кластере: &lt;br /&gt;
&amp;lt;math&amp;gt;CF = (N, \vec{LS}, SS)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - количество элементов входных данных, содержащихся в кластере, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; - линейная сумма входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}\vec{X_i}&amp;lt;/math&amp;gt;), &amp;lt;math&amp;gt;SS&amp;lt;/math&amp;gt; - сумма квадратов входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}{\vec{X_i}}^2&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Теорема&#039;&#039;&#039; Пусть &amp;lt;math&amp;gt;CF_1 = (N_1, \vec{LS_1}, SS_1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;CF_2 = (N_1, \vec{LS_2}, SS_2)&amp;lt;/math&amp;gt; - CF векторы двух непересекающихся кластеров. Тогда при их объединении образуется кластер со следующим CF вектором: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF = CF_1 + CF_2 = (N_1+N_2, \vec{LS_1}+\vec{LS_2}, SS_1+SS_2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Из указанных выше определения и теоремы вытекает тот факт, что при объединении кластеров их CF вектор может вычисляться инкрементно и точно. &lt;br /&gt;
Легко показать, что вычислить величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;, как и обычные метрики, также не составит труда.&lt;br /&gt;
&lt;br /&gt;
Таким образом, в данном случае информацией о кластере является не весь набор точек, а вектор CF. Хранение одного только вектора может показаться неэффективным, но этого вполне достаточно для оперирования всеми необходимыми метриками, на основе которых принимаются решения в алгоритме BIRCH.&lt;br /&gt;
&lt;br /&gt;
==== Кластерное дерево ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; &#039;&#039;&#039;Кластерное дерево (CF Tree)&#039;&#039;&#039; - это взвешенно сбалансированное дерево с двумя параметрами: &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - коэффициент разветвления, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - пороговая величина.&lt;br /&gt;
&lt;br /&gt;
Каждый нелистьевой узел дерева имеет не более чем &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; вхождений узлов следующей формы: &amp;lt;math&amp;gt;[CF_i,child_i]&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i=1,2,...,B&amp;lt;/math&amp;gt;, &#039;&#039;child&#039;&#039; - указатель на i-й дочерний узел, &amp;lt;math&amp;gt;CF_i&amp;lt;/math&amp;gt; - CF вектор соответствующего подкластера.&lt;br /&gt;
&lt;br /&gt;
Каждый листьевой узел имеет ссылку на два соседних узла (&#039;&#039;prev&#039;&#039; и &#039;&#039;next&#039;&#039;) для того, чтобы связать все узлы для эффективного сканирования.&lt;br /&gt;
Все листьевые узлы должны удовлетворять пороговому ограничению &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, т.е. диаметр (радиус) не должен превосходить &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;.&lt;br /&gt;
В процессе вставки новых данных CF дерево строится динамически. Оно использует вставку данных для кластеризации точно также как &amp;lt;math&amp;gt;B+&amp;lt;/math&amp;gt; [https://ru.wikipedia.org/wiki/B%2B-%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE дерево] использует её для поиска.&lt;br /&gt;
CF дерево очень компактно, поскольку каждый листьевой узел - это не просто точка, а подкластер (который объединяет множество точек с учётом ограничения &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Операция вставки в &#039;&#039;&#039;CF&#039;&#039;&#039; дерево ====&lt;br /&gt;
&lt;br /&gt;
Опишем алгоритм вставки элемнта &amp;lt;math&amp;gt;Ent&amp;lt;/math&amp;gt; в CF дерево:&lt;br /&gt;
&lt;br /&gt;
1) &#039;&#039;Определение подходящего листа&#039;&#039;: Начиная с корня, алгоритм рекурсивно спускается по CF дереву, выбирая &#039;&#039;&#039;ближайший&#039;&#039;&#039; дочерний узел в соответствии с выбранной метрикой &amp;lt;math&amp;gt;D0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D4&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &#039;&#039;Преобразование листа&#039;&#039;: Когда алгоритм доходит до листа, он находит ближайшую листьевой элемент, скажем, &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;, а затем проверяет, можно ли добавить &#039;&#039;Ent&#039;&#039; к &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt; без нарушения порогового условия. Если да, то с учётом этого изменяется CF вектор для &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;; если нет, то &#039;&#039;Ent&#039;&#039; становится новым элементом листа. Если в листе для этого достаточно места, то шаг окончен, иначе он должен &amp;quot;расщепиться&amp;quot;. Расщепление узла производится при помощи выбора за основу наиболее удалённой друг от друга пары элементов и перераспределение оставшихся элементов в соответствии с выбранным критерием близости.&lt;br /&gt;
&lt;br /&gt;
3) &#039;&#039;Преобразование пути к листу&#039;&#039;: После вставки &#039;&#039;Ent&#039;&#039; в лист мы должны обновить информацию о CF для каждого нелистьевого элемента на пути к листу. При отсутствии расщепления это означает простое сложение CF векторов для отражения факта добавления &#039;&#039;Ent&#039;&#039;. Расщепление листа же требует вставки нового нелистьевого элемента в родительский узел для задания только что созданного листа. Если у родителя есть место для этого элемента, то необходимо просто преобразовать CF векторы на всех более высоких уровнях. В общем случае, однако, нам также придётся расщепить родительский узел, и так далее до корня. Если расщеплён корень, то высота дерева увеличивается на единицу.&lt;br /&gt;
&lt;br /&gt;
4) &#039;&#039;Улучшение слияния&#039;&#039;: Расщепление вызвано ограничением на размер узла, который не зависит от кластеризационных свойств данных. Если во входящем потоке присутствуют &amp;quot;искажённые&amp;quot; (из областей с низкой плотностью) данные, это может повлиять на качество кластеризации, а также уменьшить эффективность использования памяти. Дополнительный шаг алгоритма помогает решить эти проблемы: предположим, что произошло расщепление листа, и распространение этого процесса остановилось на некотором нелистьевом узле &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt;, то есть &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; может вместить дополнительный элемент, полученный после расщепления. Теперь мы сканируем узел &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; для нахождения двух наиболее близких элементов. Если это не пара, отвечающая расщеплению, мы пытаемся объединить их и поставить в соответствие два дочерних узла. Если количество элементов в дочерних узлах  больше B, мы снова расщепляем результат объединения.&lt;br /&gt;
В процессе повторного расщепления, в случае, если один источник собирает достаточно элементов для того, чтобы полностью заполнить узел, оставшиеся элементы передаются другом источнику. В итоге, если объединённые элементы помещаются в одном узле, в нём освобождается место для ещё одного элемента. Тем самым увеличивается степень использования свободного пространства и откладывается дальнейшее расщепление. В ином случае мы улучшаем распределение элементов в двух ближайших подкластерах.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро алгоритма заключается в многократном выполнении операции вставки нового элемента в дерево, в процессе чего требуется вычисление следующих величин:&lt;br /&gt;
&lt;br /&gt;
* радиуса &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; или диаметра &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластерного элемента. Выполняется при попытке вставить новый элемент в один из подкластеров листьевого узла дерева.&lt;br /&gt;
&lt;br /&gt;
* расстояния между двумя элементами. Выполняется при поиске ближайшего по отношению к новому элементу подкластера в узле дерева по одной из рассмотренных в разд. 1.2.1 метрик &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Зная характеристики кластерных элементов &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;, в результате алгебраических преобразований можно получить следующие упрощенные формулы вычисления необходимых значений:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\vec{X_0} = \frac{\vec{LS}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{SS - 2\vec{X_0}\vec{LS} + N(\vec{X_0})^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{2(N*SS - (\vec{LS})^2)}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{N_1*SS_2 + N_2*SS_1 - 2\vec{LS_1}\vec{LS_2}}{N_1*N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{2((N_1+N_2)(SS_1+SS_2)-(\vec{LS_1}+\vec{LS_2})^2)}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Реализация алгоритма BIRCH состояит из следующих четырёх фаз:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 1&#039;&#039;&#039;. Главной задачей фазы 1 является сканирование всех данных и построение в памяти исходного CF дерева, используя заданное количество памяти. Это дерево стремится отразить информацию о кластеризации данных настолько хорошо, насколько это позволяют ограничения по памяти. При этом плотно распределённые данные группируются в подкластеры, а более разрозненные данные удаляются. После завершения фазы 1 вспомогательные вычисления в дальнейших фазах будут:&lt;br /&gt;
&lt;br /&gt;
1) быстрее, потому что (а) больше не нужны операции ввода-вывода, (b) проблема кластеризации начальных данных упрощается до проблемы кластеризации подкластеров в листьях;&lt;br /&gt;
&lt;br /&gt;
2) точнее, потому что (а) большинство данных с низкой плотностью удалены, (b) оставшиеся данные распределены оптимально (в соответствии с доступным количеством памяти);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 2&#039;&#039;&#039;. Данная фаза является опциональной. Известно, что существующие методы глобальной кластеризации, используемые в рамках фазы 3, имеют различные диапазоны входных значений, при которых их реализация наиболее эффективна. Поэтому потенциально существует пробел между размером фазы 1 и входными значениями фазы 3. И фаза 2 как раз является недостающим связующим звеном: так же как и фаза 1, она сканирует листьевые элементы начального CF дерева для того, чтобы построить меньшее дерево, удаляя ещё больше элементов с низкой плотностью и группируя переполненные подкластеры в большие кластеры.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 3&#039;&#039;&#039;. В данной фазе для листьевых элементов применяется (любой подходящий) алгоритм глобальной кластеризации. Существующие алгоритмы кластеризации наборов точек могут также работать с наборами подкластеров, каждый из которых представлен своим CF вектором. Зная CF вектор, можно вычислить центроид и в дальнейшем заменить всю информацию о кластере этим значением (этого достаточно для вычисления большинства необходимых метрик). После фазы 3 мы получаем набор кластеров, который отражает основные характеристики распределяемых данных.&lt;br /&gt;
Однако, всё ещё могут оставаться некоторые неточности, для устранения которых существует фаза 4.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 4&#039;&#039;&#039;. Данная фаза является опциональной и влечёт за собой затраты на дополнительное сканирование данных для корректировки неточностей и дальнейшего улучшения кластеризации. Фаза 4 использует центроиды кластеров, полученные в фазе 3 для как основы и перераспределяет точки входных данных в ближайшие для них основы для получения нового списка кластеров. Фаза 4, если это необходимо пользователю, может быть расширена дополнительными проходами для уверенности в том, что результат приближается к оптимальному.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Последовательную реализацию основных операций алгоритма BIRCH можно продемонстрировать на примере следующего фрагмента кода на языке C++:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot;&amp;gt;&lt;br /&gt;
void CF_Node::insert(const CF_Cluster &amp;amp;entry)&lt;br /&gt;
{&lt;br /&gt;
    //Находим ближайший к новому элементу подкластер в узле&lt;br /&gt;
    СF_Vector_it closest = entry.findClosest(subclusters);&lt;br /&gt;
    //Если узел пустой, добавляем в него новый подкластер&lt;br /&gt;
    if (closest == subclusters.end()) {&lt;br /&gt;
        subclusters.push_back(entry);&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    closest-&amp;gt;add(entry);&lt;br /&gt;
    //Если узел является листьевым, и ближайший подкластер не может вместить&lt;br /&gt;
    //новый элемент, добавляем в узел новый подкластер&lt;br /&gt;
    if (leaf) {&lt;br /&gt;
        if (closest-&amp;gt;D &amp;gt; threshold) {&lt;br /&gt;
            closest-&amp;gt;remove(entry);&lt;br /&gt;
            subclusters.push_back(entry);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else {&lt;br /&gt;
        CF_Node *node = closest-&amp;gt;child;&lt;br /&gt;
        node-&amp;gt;insert(entry);&lt;br /&gt;
        //Если при добавлении нового элемента в дочерний узел тот переполнился,&lt;br /&gt;
        //расщепляем его        &lt;br /&gt;
        if (node-&amp;gt;getSubclusters().size() &amp;gt; bFactor) {&lt;br /&gt;
            CF_Vector newClusters = node-&amp;gt;splitNode();&lt;br /&gt;
            delete node;&lt;br /&gt;
            subclusters.erase(closest);&lt;br /&gt;
            subclusters.insert(subclusters.end(), newClusters.begin(), newClusters.end());&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    //Если узел является корневым и он переполнен, расщепляем его&lt;br /&gt;
    if (root &amp;amp;&amp;amp; subclusters.size() &amp;gt; bFactor) {&lt;br /&gt;
        subclusters = splitNode();&lt;br /&gt;
        leaf = false;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
CF_Vector CF_Node::splitNode()&lt;br /&gt;
{&lt;br /&gt;
    if (subclusters.size() &amp;lt; 2)&lt;br /&gt;
        return (root) ? subclusters : CF_Vector{CF_Cluster(this)};&lt;br /&gt;
    //Находим пару наиболее удаленных друг от друга подкластеров&lt;br /&gt;
    CF_Vector_it pole1, pole2;&lt;br /&gt;
    data_t longestDist = 0.0;&lt;br /&gt;
    for (auto lhs = subclusters.begin(); lhs != subclusters.end() - 1; ++lhs) {&lt;br /&gt;
        for (auto rhs = lhs + 1; rhs != subclusters.end(); ++rhs) {&lt;br /&gt;
            auto distance = getDistance(*lhs, *rhs);&lt;br /&gt;
            if (distance &amp;gt; longestDist) {&lt;br /&gt;
                longestDist = distance;&lt;br /&gt;
                pole1 = lhs;&lt;br /&gt;
                pole2 = rhs;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    //Разделяем множество всех подкластеров узла на две части&lt;br /&gt;
    CF_Vector subclusters1, subclusters2;&lt;br /&gt;
    for (auto it = subclusters.begin(); it != subclusters.end(); ++it) {&lt;br /&gt;
        if (getDistance(*it, *pole1) &amp;lt; getDistance(*it, *pole2))&lt;br /&gt;
            subclusters1.push_back(*it);&lt;br /&gt;
        else&lt;br /&gt;
            subclusters2.push_back(*it);&lt;br /&gt;
    }&lt;br /&gt;
    //Создаем два новых узла&lt;br /&gt;
    CF_Node *node1 = new CF_Node(threshold, bFactor, count, leaf, subclusters1),&lt;br /&gt;
            *node2 = new CF_Node(threshold, bFactor, count, leaf, subclusters2);&lt;br /&gt;
    //Связываем листья&lt;br /&gt;
    if (leaf) {&lt;br /&gt;
        if (prevLeaf) {&lt;br /&gt;
            node1-&amp;gt;setPrevLeaf(prevLeaf);&lt;br /&gt;
            prevLeaf-&amp;gt;setNextLeaf(node1);&lt;br /&gt;
        }&lt;br /&gt;
        if (nextLeaf) {&lt;br /&gt;
            node2-&amp;gt;setNextLeaf(nextLeaf);&lt;br /&gt;
            nextLeaf-&amp;gt;setPrevLeaf(node2);&lt;br /&gt;
        }&lt;br /&gt;
        node1-&amp;gt;setNextLeaf(node2);&lt;br /&gt;
        node2-&amp;gt;setPrevLeaf(node1);&lt;br /&gt;
    }&lt;br /&gt;
    CF_Cluster cluster1(node1), cluster2(node2);&lt;br /&gt;
    return CF_Vector{cluster1, cluster2};&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Для начала проанализируем вычислительную сложность фазы 1.&lt;br /&gt;
Максимальный размер дерева &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt; - ограничение по памяти на размер узла, а &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - общий объем памяти. Для того чтобы вставить элемент, мы должны пройти путь от корня до листа (это около &amp;lt;math&amp;gt;1+log_B\frac{M}{P}&amp;lt;/math&amp;gt; узлов). В каждом узле в поисках &amp;quot;ближайшего&amp;quot; нам необходимо просмотреть B элементов; сложность для каждого элемента пропорциональна размерности &#039;&#039;d&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Поэтому сложность вставки всех входных точек &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В случае, когда необходимо перестроить дерево, предположим, что ES - это размер CF элемента. Существует максимум &amp;lt;math&amp;gt;\frac{M}{ES}&amp;lt;/math&amp;gt; листьевых элементов для вставки, поэтому сложность повторной вставки листьевых элементов &amp;lt;math&amp;gt;O(d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Количество итераций перестройки дерева зависит от пороговой величины. На самом деле, это около &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; (двоичное основание появилось из-за того, что мы не можем провести оценку более чем в 2 раза отличающуюся от текущего размера). &amp;lt;math&amp;gt;N_0&amp;lt;/math&amp;gt; - это число входных точек, загруженных в память с пороговым ограничением &amp;lt;math&amp;gt;T_0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Соответственно, итоговая сложность фазы 1 &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P})+log_2\frac{N}{N_0}*d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Анализ фазы 2 проводится аналогично.&lt;br /&gt;
&lt;br /&gt;
Что касается операций ввода-вывода, то в фазе 1 данные сканируются один раз, а в фазе 2 не сканируются вовсе.&lt;br /&gt;
Некоторое количество вычислений связано с удалением точек из областей с низкой плотностью.&lt;br /&gt;
Если количество доступной для этой операции памяти не больше &#039;&#039;M&#039;&#039; и проведено порядка &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; перестроек дерева, то сложность ввода-вывода для фазы 1 существенно не отличается от сложности чтения из файла. Основываясь рассуждениях выше, сложность фаз 1 и 2 будет линейно увеличиваться с ростом N.&lt;br /&gt;
&lt;br /&gt;
В фазе 3 нет операций ввода-вывода. Её сложность ограничена константой, которая зависит от максимального размера входных данных, и варианта выбранного алгоритма для кластеризации. &lt;br /&gt;
&lt;br /&gt;
Фаза 4 снова сканирует данные и записывает каждую точку в подходящий кластер; время работы пропорционально &amp;lt;math&amp;gt;N*K&amp;lt;/math&amp;gt;.   &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
=== Вычисление расстояния ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2=\frac{N_1\cdot SS_2+N_2\cdot SS_1-2*\vec{LS_1}\cdot \vec{LS_2}}{N_1\cdot N_2}&amp;lt;/math&amp;gt;, где&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF_1=[N_1,\vec{LS_1},SS_1]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF_2=[N_2,\vec{LS_2},SS_2]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:ZgYL51QJsQk.jpg|600px|thumb|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Поиск ближайшего подкластера ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;E&amp;lt;/math&amp;gt; - новый элемент&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF_i, i = 1,...,B&amp;lt;/math&amp;gt; - подкластеры узла&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - операция min&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\rho&amp;lt;/math&amp;gt; - нахождение расстояния&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:PFA16KHUQ3I.jpg|600px|thumb|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Скалярное произведение ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;s = \vec{x}\cdot\vec{y}=\sum_{i=1}^d x_i\cdot y_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Xb7FYXVMPpQ.jpg|600px|thumb|center]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельно могут быть выполнены следующие шаги алгоритма:&lt;br /&gt;
* Нахождение ближайшего к новому элементу подкластера в узле при выполнении операции вставки. Это возможно за счет того, что расстояние между парами элементов может быть вычислено независимо друг от друга. Сложность &lt;br /&gt;
* Вычисление величин &amp;lt;math&amp;gt;\vec{LS},\vec{X0}, R, D, D_0-D_4&amp;lt;/math&amp;gt;, в процессе чего выполняются операции сложения и скалярного произведения векторов.&lt;br /&gt;
&lt;br /&gt;
Другим способом параллелизации алгоритма может служить создание и заполнение сразу множества кластерных деревьев, между которыми будут распределены входные данные. Множество всех подкластеров листьевых узлов полученных таким образом деревьев может быть подвергнуто глобальной кластеризации с помощью какого-либо из известных параллельных алгоритмов, например, k-средних&amp;lt;ref&amp;gt;[http://people.du.ac.in/~ngupta/Publications/PBIRCH%20A%20Sacalabel%20Paralllel%20Clustering.pdf A Garg, N Gupta PBIRCH: A Scalable Parallel Clustering algorithm for Incremental Data]&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;
* Набор из &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек &amp;lt;math&amp;gt;\{X_i\}, i=1,...,N&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Кластерное дерево с не более чем &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt; узлами.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Достоинства алгоритма ===&lt;br /&gt;
По сравнению с предыдущими методами BIRCH обладает следующими достоинствами:&lt;br /&gt;
&lt;br /&gt;
1. BIRCH является локальным алгоритмом, то есть каждое решение о каждом элементе кластера принимается без повторного сканирования данных или уже существующих кластеров. Используются только метрики, отражающие близость элементов друг к другу.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH использует факт неравномерного распределения данных в пространстве и поэтому не все данные рассматриваются как одинаково важные для построения кластера. Области с большой плотностью обрабатываются как единый кластер. Данные в более разреженных областях могут удаляться (опционально).&lt;br /&gt;
&lt;br /&gt;
3. BIRCH использует всю доступную память для получения наилучших из возможных подкластеров, в то же время минимизируя затраты на операции ввода/вывода. Оптимизация процесса кластеризации достигается за счет использования взвешенно-сбалансированного дерева. При этом время исполнения линейно.&lt;br /&gt;
&lt;br /&gt;
4. BIRCH не требует всего набора данных заранее (при этом просматривает его всего один раз).&lt;br /&gt;
&lt;br /&gt;
=== Недостатки алгоритма ===&lt;br /&gt;
&lt;br /&gt;
1. Алгоритм позволяет работать только с числовыми данными.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH хорошо выделяет только кластеры сферической формы.&lt;br /&gt;
&lt;br /&gt;
3. Существует необходимость в задании пороговых значений.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
В составе пакетов и библиотек:&lt;br /&gt;
* [http://scikit-learn.org/stable/modules/generated/sklearn.cluster.Birch.html scikit-learn]&lt;br /&gt;
* [http://cucis.ece.northwestern.edu/projects/DMS/MineBench.html NU-MineBench]&lt;br /&gt;
Пользовательские реализации:&lt;br /&gt;
* [https://code.google.com/archive/p/jbirch/ JBIRCH]&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Светлана Морозова</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13844</id>
		<title>Участник:Smirnov.maxim/BIRCH</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13844"/>
		<updated>2016-10-26T07:39:53Z</updated>

		<summary type="html">&lt;p&gt;Светлана Морозова: /* Информационный граф */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Авторы: [[Участник:Светлана Морозова|Морозова Светлана]], [[Участник:Smirnov.maxim|Смирнов Максим]].&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Нахождение полезных для анализа закономерностей в больших объёмах данных с недавних пор вызывает значительный интерес. В связи с этим ввелось и стало активно развиваться такое понятие как &#039;&#039;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7 кластеризация]&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Ранние работы и алгоритмы, разработанные в этой области, не уделяли достаточного внимания анализу очень больших наборов данных или минимизации издержек на процессы ввода-вывода.&lt;br /&gt;
Решением этих проблем стал алгоритм, известный как BIRCH.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIRCH&#039;&#039;&#039;&amp;lt;ref&amp;gt;[http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf Нейский И.М. Классификация и сравнение методов кластеризации]&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;[http://www.cs.sfu.ca/CourseCentral/459/han/papers/zhang96.pdf T Zhang, R Ramakrishnan, M Livny. BIRCH: An Efficient Data Clustering Method for Very Large Databases]&amp;lt;/ref&amp;gt; (balanced iterative reducing and clustering using hierarchies)- алгоритм, применяемый в области [https://ru.wikipedia.org/wiki/Data_mining Data mining] и использующий принципы [https://ru.wikipedia.org/wiki/%D0%98%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F иерархической кластеризации].&lt;br /&gt;
&lt;br /&gt;
Если имеется очень большой набор данных, то в пространстве он распределен, как правило, неравномерно. Кластерный анализ определяет места наибольшего и наименьшего скоплений, чтобы таким образом понять всю картину целиком. Кроме того, полученные кластеры визуализируются гораздо нагляднее, чем начальные &amp;quot;сырые&amp;quot; данные.&lt;br /&gt;
Задачей алгоритмов кластеризации является не только простое разбиение данных на кластеры, но и работа в рамках ограниченного объёма доступной памяти (как правило, её объём гораздо меньше, чем размер исходного набора данных) и минимизация времени, требуемого на операции ввода-вывода.&lt;br /&gt;
&lt;br /&gt;
Для наилучшего решения этих проблем BIRCH распределяет входящие данные по кластерам динамически. Для эффективной кластеризации алгоритму требуется всего одно сканирование данных (т.е. с увеличением количества данных сложность увеличивается линейно). А при помощи одной (или более) дополнительных итераций можно и далее улучшать эффективность. BIRCH также является первым алгоритмом, предложенным для эффективного управления &amp;quot;шумами&amp;quot; (данными, которые не вписываются в общее представление модели).&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Теоретическая основа ===&lt;br /&gt;
&lt;br /&gt;
Пусть в кластере имеются &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}, i=1,2,...,N&amp;lt;/math&amp;gt;.&lt;br /&gt;
Тогда &#039;&#039;&#039;центроид&#039;&#039;&#039; &amp;lt;math&amp;gt;{\vec{{X_0}}}&amp;lt;/math&amp;gt;, &#039;&#039;&#039;радиус&#039;&#039;&#039; &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &#039;&#039;&#039;диаметр&#039;&#039;&#039; &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластера определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;{\vec{X_0}}=\frac{\sum_{i=1}^N\vec{X_i}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{\sum_{i=1}^N{(\vec{X_i} - \vec{X_0})}^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{\sum_{i=1}^N\sum_{j=1}^N{(\vec{X_i} - \vec{X_j})}^2}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; - это среднее расстояние от каждой точки до центроида. &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; - это среднее расстояние между парами в кластере. Данные величины являются альтернативными метриками плотности кластера относительно центроида.&lt;br /&gt;
&lt;br /&gt;
Для измерения близости друг к другу двух кластеров вводятся следующие метрики:&lt;br /&gt;
&lt;br /&gt;
пусть даны центроиды двух кластеров &amp;lt;math&amp;gt;\vec{X_{01}}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\vec{X_{02}}&amp;lt;/math&amp;gt;.&lt;br /&gt;
Евклидова метрика &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt; и метрика Манхэттена &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt; между двумя кластерами определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_0 = ((\vec{X_{01}}-\vec{X_{02}})^2)^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_1 = |\vec{X_{01}}-\vec{X_{02}}| = \sum_{i=1}^d |{\vec{X_{01}}}^{(i)}-{\vec{X_{02}}}^{(i)}| &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть имеются два кластера, содержащих соответственно  &amp;lt;math&amp;gt;N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;N_2&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i= 1,2, ...,N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\{\vec{X_j}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j= N_1+1,N_1+2, ...,N_1+N_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Среднее расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &#039;&#039;&#039;среднее внутрикластерное расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &#039;&#039;&#039;дисперсия&#039;&#039;&#039; &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; для двух кластеров определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{\sum_{i=1}^{N_1}\sum_{j=N_1+1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{N_1N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{\sum_{i=1}^{N_1+N_2}\sum_{j=1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_4 = \sum_{k=1}^{N_1+N_2}(\vec{X_k} - \frac{\sum_{i=1}^{N_1+N_2}\vec{X_i}}{N_1+N_2})^2 - \sum_{i=1}^{N_1}(\vec{X_i} - \frac{\sum_{i=1}^{N_1}\vec{X_i}}{N_1})^2 - \sum_{j=N_1+1}^{N_1+N_2}(\vec{X_j} - \frac{\sum_{i=N_1+1}^{N_1+N_2}\vec{X_i}}{N_2})^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Таким образом, величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; относятся к отдельным кластерам, а &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; - к объединению двух кластеров.&lt;br /&gt;
&lt;br /&gt;
=== Кластерный элемент и кластерное дерево ===&lt;br /&gt;
&lt;br /&gt;
В основе концепции алгоритма BIRCH лежат понятия &#039;&#039;&#039;кластерного элемента&#039;&#039;&#039; и &#039;&#039;&#039;кластерного дерева (CF Tree)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====Кластерный элемент ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; Пусть в кластере содержатся  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности  &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;:&amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;i=1,2,...,N&amp;lt;/math&amp;gt;. &lt;br /&gt;
&#039;&#039;&#039;Кластерный элемент (CF)&#039;&#039;&#039; - тройка чисел, характеризующая информацию о кластере: &lt;br /&gt;
&amp;lt;math&amp;gt;CF = (N, \vec{LS}, SS)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - количество элементов входных данных, содержащихся в кластере, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; - линейная сумма входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}\vec{X_i}&amp;lt;/math&amp;gt;), &amp;lt;math&amp;gt;SS&amp;lt;/math&amp;gt; - сумма квадратов входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}{\vec{X_i}}^2&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Теорема&#039;&#039;&#039; Пусть &amp;lt;math&amp;gt;CF_1 = (N_1, \vec{LS_1}, SS_1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;CF_2 = (N_1, \vec{LS_2}, SS_2)&amp;lt;/math&amp;gt; - CF векторы двух непересекающихся кластеров. Тогда при их объединении образуется кластер со следующим CF вектором: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF = CF_1 + CF_2 = (N_1+N_2, \vec{LS_1}+\vec{LS_2}, SS_1+SS_2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Из указанных выше определения и теоремы вытекает тот факт, что при объединении кластеров их CF вектор может вычисляться инкрементно и точно. &lt;br /&gt;
Легко показать, что вычислить величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;, как и обычные метрики, также не составит труда.&lt;br /&gt;
&lt;br /&gt;
Таким образом, в данном случае информацией о кластере является не весь набор точек, а вектор CF. Хранение одного только вектора может показаться неэффективным, но этого вполне достаточно для оперирования всеми необходимыми метриками, на основе которых принимаются решения в алгоритме BIRCH.&lt;br /&gt;
&lt;br /&gt;
==== Кластерное дерево ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; &#039;&#039;&#039;Кластерное дерево (CF Tree)&#039;&#039;&#039; - это взвешенно сбалансированное дерево с двумя параметрами: &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - коэффициент разветвления, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - пороговая величина.&lt;br /&gt;
&lt;br /&gt;
Каждый нелистьевой узел дерева имеет не более чем &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; вхождений узлов следующей формы: &amp;lt;math&amp;gt;[CF_i,child_i]&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i=1,2,...,B&amp;lt;/math&amp;gt;, &#039;&#039;child&#039;&#039; - указатель на i-й дочерний узел, &amp;lt;math&amp;gt;CF_i&amp;lt;/math&amp;gt; - CF вектор соответствующего подкластера.&lt;br /&gt;
&lt;br /&gt;
Каждый листьевой узел имеет ссылку на два соседних узла (&#039;&#039;prev&#039;&#039; и &#039;&#039;next&#039;&#039;) для того, чтобы связать все узлы для эффективного сканирования.&lt;br /&gt;
Все листьевые узлы должны удовлетворять пороговому ограничению &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, т.е. диаметр (радиус) не должен превосходить &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;.&lt;br /&gt;
В процессе вставки новых данных CF дерево строится динамически. Оно использует вставку данных для кластеризации точно также как &amp;lt;math&amp;gt;B+&amp;lt;/math&amp;gt; [https://ru.wikipedia.org/wiki/B%2B-%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE дерево] использует её для поиска.&lt;br /&gt;
CF дерево очень компактно, поскольку каждый листьевой узел - это не просто точка, а подкластер (который объединяет множество точек с учётом ограничения &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Операция вставки в &#039;&#039;&#039;CF&#039;&#039;&#039; дерево ====&lt;br /&gt;
&lt;br /&gt;
Опишем алгоритм вставки элемнта &amp;lt;math&amp;gt;Ent&amp;lt;/math&amp;gt; в CF дерево:&lt;br /&gt;
&lt;br /&gt;
1) &#039;&#039;Определение подходящего листа&#039;&#039;: Начиная с корня, алгоритм рекурсивно спускается по CF дереву, выбирая &#039;&#039;&#039;ближайший&#039;&#039;&#039; дочерний узел в соответствии с выбранной метрикой &amp;lt;math&amp;gt;D0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D4&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &#039;&#039;Преобразование листа&#039;&#039;: Когда алгоритм доходит до листа, он находит ближайшую листьевой элемент, скажем, &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;, а затем проверяет, можно ли добавить &#039;&#039;Ent&#039;&#039; к &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt; без нарушения порогового условия. Если да, то с учётом этого изменяется CF вектор для &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;; если нет, то &#039;&#039;Ent&#039;&#039; становится новым элементом листа. Если в листе для этого достаточно места, то шаг окончен, иначе он должен &amp;quot;расщепиться&amp;quot;. Расщепление узла производится при помощи выбора за основу наиболее удалённой друг от друга пары элементов и перераспределение оставшихся элементов в соответствии с выбранным критерием близости.&lt;br /&gt;
&lt;br /&gt;
3) &#039;&#039;Преобразование пути к листу&#039;&#039;: После вставки &#039;&#039;Ent&#039;&#039; в лист мы должны обновить информацию о CF для каждого нелистьевого элемента на пути к листу. При отсутствии расщепления это означает простое сложение CF векторов для отражения факта добавления &#039;&#039;Ent&#039;&#039;. Расщепление листа же требует вставки нового нелистьевого элемента в родительский узел для задания только что созданного листа. Если у родителя есть место для этого элемента, то необходимо просто преобразовать CF векторы на всех более высоких уровнях. В общем случае, однако, нам также придётся расщепить родительский узел, и так далее до корня. Если расщеплён корень, то высота дерева увеличивается на единицу.&lt;br /&gt;
&lt;br /&gt;
4) &#039;&#039;Улучшение слияния&#039;&#039;: Расщепление вызвано ограничением на размер узла, который не зависит от кластеризационных свойств данных. Если во входящем потоке присутствуют &amp;quot;искажённые&amp;quot; (из областей с низкой плотностью) данные, это может повлиять на качество кластеризации, а также уменьшить эффективность использования памяти. Дополнительный шаг алгоритма помогает решить эти проблемы: предположим, что произошло расщепление листа, и распространение этого процесса остановилось на некотором нелистьевом узле &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt;, то есть &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; может вместить дополнительный элемент, полученный после расщепления. Теперь мы сканируем узел &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; для нахождения двух наиболее близких элементов. Если это не пара, отвечающая расщеплению, мы пытаемся объединить их и поставить в соответствие два дочерних узла. Если количество элементов в дочерних узлах  больше B, мы снова расщепляем результат объединения.&lt;br /&gt;
В процессе повторного расщепления, в случае, если один источник собирает достаточно элементов для того, чтобы полностью заполнить узел, оставшиеся элементы передаются другом источнику. В итоге, если объединённые элементы помещаются в одном узле, в нём освобождается место для ещё одного элемента. Тем самым увеличивается степень использования свободного пространства и откладывается дальнейшее расщепление. В ином случае мы улучшаем распределение элементов в двух ближайших подкластерах.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро алгоритма заключается в многократном выполнении операции вставки нового элемента в дерево, в процессе чего требуется вычисление следующих величин:&lt;br /&gt;
&lt;br /&gt;
* радиуса &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; или диаметра &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластерного элемента. Выполняется при попытке вставить новый элемент в один из подкластеров листьевого узла дерева.&lt;br /&gt;
&lt;br /&gt;
* расстояния между двумя элементами. Выполняется при поиске ближайшего по отношению к новому элементу подкластера в узле дерева по одной из рассмотренных в разд. 1.2.1 метрик &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Зная характеристики кластерных элементов &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;, в результате алгебраических преобразований можно получить следующие упрощенные формулы вычисления необходимых значений:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\vec{X_0} = \frac{\vec{LS}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{SS - 2\vec{X_0}\vec{LS} + N(\vec{X_0})^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{2(N*SS - (\vec{LS})^2)}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{N_1*SS_2 + N_2*SS_1 - 2\vec{LS_1}\vec{LS_2}}{N_1*N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{2((N_1+N_2)(SS_1+SS_2)-(\vec{LS_1}+\vec{LS_2})^2)}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Реализация алгоритма BIRCH состояит из следующих четырёх фаз:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 1&#039;&#039;&#039;. Главной задачей фазы 1 является сканирование всех данных и построение в памяти исходного CF дерева, используя заданное количество памяти. Это дерево стремится отразить информацию о кластеризации данных настолько хорошо, насколько это позволяют ограничения по памяти. При этом плотно распределённые данные группируются в подкластеры, а более разрозненные данные удаляются. После завершения фазы 1 вспомогательные вычисления в дальнейших фазах будут:&lt;br /&gt;
&lt;br /&gt;
1) быстрее, потому что (а) больше не нужны операции ввода-вывода, (b) проблема кластеризации начальных данных упрощается до проблемы кластеризации подкластеров в листьях;&lt;br /&gt;
&lt;br /&gt;
2) точнее, потому что (а) большинство данных с низкой плотностью удалены, (b) оставшиеся данные распределены оптимально (в соответствии с доступным количеством памяти);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 2&#039;&#039;&#039;. Данная фаза является опциональной. Известно, что существующие методы глобальной кластеризации, используемые в рамках фазы 3, имеют различные диапазоны входных значений, при которых их реализация наиболее эффективна. Поэтому потенциально существует пробел между размером фазы 1 и входными значениями фазы 3. И фаза 2 как раз является недостающим связующим звеном: так же как и фаза 1, она сканирует листьевые элементы начального CF дерева для того, чтобы построить меньшее дерево, удаляя ещё больше элементов с низкой плотностью и группируя переполненные подкластеры в большие кластеры.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 3&#039;&#039;&#039;. В данной фазе для листьевых элементов применяется (любой подходящий) алгоритм глобальной кластеризации. Существующие алгоритмы кластеризации наборов точек могут также работать с наборами подкластеров, каждый из которых представлен своим CF вектором. Зная CF вектор, можно вычислить центроид и в дальнейшем заменить всю информацию о кластере этим значением (этого достаточно для вычисления большинства необходимых метрик). После фазы 3 мы получаем набор кластеров, который отражает основные характеристики распределяемых данных.&lt;br /&gt;
Однако, всё ещё могут оставаться некоторые неточности, для устранения которых существует фаза 4.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 4&#039;&#039;&#039;. Данная фаза является опциональной и влечёт за собой затраты на дополнительное сканирование данных для корректировки неточностей и дальнейшего улучшения кластеризации. Фаза 4 использует центроиды кластеров, полученные в фазе 3 для как основы и перераспределяет точки входных данных в ближайшие для них основы для получения нового списка кластеров. Фаза 4, если это необходимо пользователю, может быть расширена дополнительными проходами для уверенности в том, что результат приближается к оптимальному.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Последовательную реализацию основных операций алгоритма BIRCH можно продемонстрировать на примере следующего фрагмента кода на языке C++:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot;&amp;gt;&lt;br /&gt;
void CF_Node::insert(const CF_Cluster &amp;amp;entry)&lt;br /&gt;
{&lt;br /&gt;
    //Находим ближайший к новому элементу подкластер в узле&lt;br /&gt;
    СF_Vector_it closest = entry.findClosest(subclusters);&lt;br /&gt;
    //Если узел пустой, добавляем в него новый подкластер&lt;br /&gt;
    if (closest == subclusters.end()) {&lt;br /&gt;
        subclusters.push_back(entry);&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    closest-&amp;gt;add(entry);&lt;br /&gt;
    //Если узел является листьевым, и ближайший подкластер не может вместить&lt;br /&gt;
    //новый элемент, добавляем в узел новый подкластер&lt;br /&gt;
    if (leaf) {&lt;br /&gt;
        if (closest-&amp;gt;D &amp;gt; threshold) {&lt;br /&gt;
            closest-&amp;gt;remove(entry);&lt;br /&gt;
            subclusters.push_back(entry);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else {&lt;br /&gt;
        CF_Node *node = closest-&amp;gt;child;&lt;br /&gt;
        node-&amp;gt;insert(entry);&lt;br /&gt;
        //Если при добавлении нового элемента в дочерний узел тот переполнился,&lt;br /&gt;
        //расщепляем его        &lt;br /&gt;
        if (node-&amp;gt;getSubclusters().size() &amp;gt; bFactor) {&lt;br /&gt;
            CF_Vector newClusters = node-&amp;gt;splitNode();&lt;br /&gt;
            delete node;&lt;br /&gt;
            subclusters.erase(closest);&lt;br /&gt;
            subclusters.insert(subclusters.end(), newClusters.begin(), newClusters.end());&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    //Если узел является корневым и он переполнен, расщепляем его&lt;br /&gt;
    if (root &amp;amp;&amp;amp; subclusters.size() &amp;gt; bFactor) {&lt;br /&gt;
        subclusters = splitNode();&lt;br /&gt;
        leaf = false;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
CF_Vector CF_Node::splitNode()&lt;br /&gt;
{&lt;br /&gt;
    if (subclusters.size() &amp;lt; 2)&lt;br /&gt;
        return (root) ? subclusters : CF_Vector{CF_Cluster(this)};&lt;br /&gt;
    //Находим пару наиболее удаленных друг от друга подкластеров&lt;br /&gt;
    CF_Vector_it pole1, pole2;&lt;br /&gt;
    data_t longestDist = 0.0;&lt;br /&gt;
    for (auto lhs = subclusters.begin(); lhs != subclusters.end() - 1; ++lhs) {&lt;br /&gt;
        for (auto rhs = lhs + 1; rhs != subclusters.end(); ++rhs) {&lt;br /&gt;
            auto distance = getDistance(*lhs, *rhs);&lt;br /&gt;
            if (distance &amp;gt; longestDist) {&lt;br /&gt;
                longestDist = distance;&lt;br /&gt;
                pole1 = lhs;&lt;br /&gt;
                pole2 = rhs;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    //Разделяем множество всех подкластеров узла на две части&lt;br /&gt;
    CF_Vector subclusters1, subclusters2;&lt;br /&gt;
    for (auto it = subclusters.begin(); it != subclusters.end(); ++it) {&lt;br /&gt;
        if (getDistance(*it, *pole1) &amp;lt; getDistance(*it, *pole2))&lt;br /&gt;
            subclusters1.push_back(*it);&lt;br /&gt;
        else&lt;br /&gt;
            subclusters2.push_back(*it);&lt;br /&gt;
    }&lt;br /&gt;
    //Создаем два новых узла&lt;br /&gt;
    CF_Node *node1 = new CF_Node(threshold, bFactor, count, leaf, subclusters1),&lt;br /&gt;
            *node2 = new CF_Node(threshold, bFactor, count, leaf, subclusters2);&lt;br /&gt;
    //Связываем листья&lt;br /&gt;
    if (leaf) {&lt;br /&gt;
        if (prevLeaf) {&lt;br /&gt;
            node1-&amp;gt;setPrevLeaf(prevLeaf);&lt;br /&gt;
            prevLeaf-&amp;gt;setNextLeaf(node1);&lt;br /&gt;
        }&lt;br /&gt;
        if (nextLeaf) {&lt;br /&gt;
            node2-&amp;gt;setNextLeaf(nextLeaf);&lt;br /&gt;
            nextLeaf-&amp;gt;setPrevLeaf(node2);&lt;br /&gt;
        }&lt;br /&gt;
        node1-&amp;gt;setNextLeaf(node2);&lt;br /&gt;
        node2-&amp;gt;setPrevLeaf(node1);&lt;br /&gt;
    }&lt;br /&gt;
    CF_Cluster cluster1(node1), cluster2(node2);&lt;br /&gt;
    return CF_Vector{cluster1, cluster2};&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Для начала проанализируем вычислительную сложность фазы 1.&lt;br /&gt;
Максимальный размер дерева &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt; - ограничение по памяти на размер узла, а &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - общий объем памяти. Для того чтобы вставить элемент, мы должны пройти путь от корня до листа (это около &amp;lt;math&amp;gt;1+log_B\frac{M}{P}&amp;lt;/math&amp;gt; узлов). В каждом узле в поисках &amp;quot;ближайшего&amp;quot; нам необходимо просмотреть B элементов; сложность для каждого элемента пропорциональна размерности &#039;&#039;d&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Поэтому сложность вставки всех входных точек &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В случае, когда необходимо перестроить дерево, предположим, что ES - это размер CF элемента. Существует максимум &amp;lt;math&amp;gt;\frac{M}{ES}&amp;lt;/math&amp;gt; листьевых элементов для вставки, поэтому сложность повторной вставки листьевых элементов &amp;lt;math&amp;gt;O(d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Количество итераций перестройки дерева зависит от пороговой величины. На самом деле, это около &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; (двоичное основание появилось из-за того, что мы не можем провести оценку более чем в 2 раза отличающуюся от текущего размера). &amp;lt;math&amp;gt;N_0&amp;lt;/math&amp;gt; - это число входных точек, загруженных в память с пороговым ограничением &amp;lt;math&amp;gt;T_0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Соответственно, итоговая сложность фазы 1 &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P})+log_2\frac{N}{N_0}*d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Анализ фазы 2 проводится аналогично.&lt;br /&gt;
&lt;br /&gt;
Что касается операций ввода-вывода, то в фазе 1 данные сканируются один раз, а в фазе 2 не сканируются вовсе.&lt;br /&gt;
Некоторое количество вычислений связано с удалением точек из областей с низкой плотностью.&lt;br /&gt;
Если количество доступной для этой операции памяти не больше &#039;&#039;M&#039;&#039; и проведено порядка &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; перестроек дерева, то сложность ввода-вывода для фазы 1 существенно не отличается от сложности чтения из файла. Основываясь рассуждениях выше, сложность фаз 1 и 2 будет линейно увеличиваться с ростом N.&lt;br /&gt;
&lt;br /&gt;
В фазе 3 нет операций ввода-вывода. Её сложность ограничена константой, которая зависит от максимального размера входных данных, и варианта выбранного алгоритма для кластеризации. &lt;br /&gt;
&lt;br /&gt;
Фаза 4 снова сканирует данные и записывает каждую точку в подходящий кластер; время работы пропорционально &amp;lt;math&amp;gt;N*K&amp;lt;/math&amp;gt;.   &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
=== Вычисление расстояния ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2=\frac{N_1\cdotSS_2+N_2\cdotSS_1-2*\vec{LS_1}\cdot\vec{LS_2}}{N_1\cdotN_2}&amp;lt;/math&amp;gt;, где&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF_1=[N_1,\vec{LS_1},SS_1]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF_2=[N_2,\vec{LS_2},SS_2]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:ZgYL51QJsQk.jpg|500px|thumb|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Поиск ближайшего подкластера ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;E&amp;lt;/math&amp;gt; - новый элемент&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF_i, i = 1,...,B&amp;lt;/math&amp;gt; - подкластеры узла&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - операция min&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\rho&amp;lt;/math&amp;gt; - нахождение расстояния&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:PFA16KHUQ3I.jpg|500px|thumb|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Скалярное произведение ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;s = \vec{x}\cdot\vec{y}=\sum_{i=1}^d x_i\cdot y_i&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Xb7FYXVMPpQ.jpg|500px|thumb|center]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельно могут быть выполнены следующие шаги алгоритма:&lt;br /&gt;
* Нахождение ближайшего к новому элементу подкластера в узле при выполнении операции вставки. Это возможно за счет того, что расстояние между парами элементов может быть вычислено независимо друг от друга. Сложность &lt;br /&gt;
* Вычисление величин &amp;lt;math&amp;gt;\vec{LS},\vec{X0}, R, D, D_0-D_4&amp;lt;/math&amp;gt;, в процессе чего выполняются операции сложения и скалярного произведения векторов.&lt;br /&gt;
&lt;br /&gt;
Другим способом параллелизации алгоритма может служить создание и заполнение сразу множества кластерных деревьев, между которыми будут распределены входные данные. Множество всех подкластеров листьевых узлов полученных таким образом деревьев может быть подвергнуто глобальной кластеризации с помощью какого-либо из известных параллельных алгоритмов, например, k-средних&amp;lt;ref&amp;gt;[http://people.du.ac.in/~ngupta/Publications/PBIRCH%20A%20Sacalabel%20Paralllel%20Clustering.pdf A Garg, N Gupta PBIRCH: A Scalable Parallel Clustering algorithm for Incremental Data]&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;
* Набор из &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек &amp;lt;math&amp;gt;\{X_i\}, i=1,...,N&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Кластерное дерево с не более чем &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt; узлами.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Достоинства алгоритма ===&lt;br /&gt;
По сравнению с предыдущими методами BIRCH обладает следующими достоинствами:&lt;br /&gt;
&lt;br /&gt;
1. BIRCH является локальным алгоритмом, то есть каждое решение о каждом элементе кластера принимается без повторного сканирования данных или уже существующих кластеров. Используются только метрики, отражающие близость элементов друг к другу.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH использует факт неравномерного распределения данных в пространстве и поэтому не все данные рассматриваются как одинаково важные для построения кластера. Области с большой плотностью обрабатываются как единый кластер. Данные в более разреженных областях могут удаляться (опционально).&lt;br /&gt;
&lt;br /&gt;
3. BIRCH использует всю доступную память для получения наилучших из возможных подкластеров, в то же время минимизируя затраты на операции ввода/вывода. Оптимизация процесса кластеризации достигается за счет использования взвешенно-сбалансированного дерева. При этом время исполнения линейно.&lt;br /&gt;
&lt;br /&gt;
4. BIRCH не требует всего набора данных заранее (при этом просматривает его всего один раз).&lt;br /&gt;
&lt;br /&gt;
=== Недостатки алгоритма ===&lt;br /&gt;
&lt;br /&gt;
1. Алгоритм позволяет работать только с числовыми данными.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH хорошо выделяет только кластеры сферической формы.&lt;br /&gt;
&lt;br /&gt;
3. Существует необходимость в задании пороговых значений.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
В составе пакетов и библиотек:&lt;br /&gt;
* [http://scikit-learn.org/stable/modules/generated/sklearn.cluster.Birch.html scikit-learn]&lt;br /&gt;
* [http://cucis.ece.northwestern.edu/projects/DMS/MineBench.html NU-MineBench]&lt;br /&gt;
Пользовательские реализации:&lt;br /&gt;
* [https://code.google.com/archive/p/jbirch/ JBIRCH]&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Светлана Морозова</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13841</id>
		<title>Участник:Smirnov.maxim/BIRCH</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13841"/>
		<updated>2016-10-26T07:32:28Z</updated>

		<summary type="html">&lt;p&gt;Светлана Морозова: /* Информационный граф */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Авторы: [[Участник:Светлана Морозова|Морозова Светлана]], [[Участник:Smirnov.maxim|Смирнов Максим]].&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Нахождение полезных для анализа закономерностей в больших объёмах данных с недавних пор вызывает значительный интерес. В связи с этим ввелось и стало активно развиваться такое понятие как &#039;&#039;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7 кластеризация]&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Ранние работы и алгоритмы, разработанные в этой области, не уделяли достаточного внимания анализу очень больших наборов данных или минимизации издержек на процессы ввода-вывода.&lt;br /&gt;
Решением этих проблем стал алгоритм, известный как BIRCH.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIRCH&#039;&#039;&#039;&amp;lt;ref&amp;gt;[http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf Нейский И.М. Классификация и сравнение методов кластеризации]&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;[http://www.cs.sfu.ca/CourseCentral/459/han/papers/zhang96.pdf T Zhang, R Ramakrishnan, M Livny. BIRCH: An Efficient Data Clustering Method for Very Large Databases]&amp;lt;/ref&amp;gt; (balanced iterative reducing and clustering using hierarchies)- алгоритм, применяемый в области [https://ru.wikipedia.org/wiki/Data_mining Data mining] и использующий принципы [https://ru.wikipedia.org/wiki/%D0%98%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F иерархической кластеризации].&lt;br /&gt;
&lt;br /&gt;
Если имеется очень большой набор данных, то в пространстве он распределен, как правило, неравномерно. Кластерный анализ определяет места наибольшего и наименьшего скоплений, чтобы таким образом понять всю картину целиком. Кроме того, полученные кластеры визуализируются гораздо нагляднее, чем начальные &amp;quot;сырые&amp;quot; данные.&lt;br /&gt;
Задачей алгоритмов кластеризации является не только простое разбиение данных на кластеры, но и работа в рамках ограниченного объёма доступной памяти (как правило, её объём гораздо меньше, чем размер исходного набора данных) и минимизация времени, требуемого на операции ввода-вывода.&lt;br /&gt;
&lt;br /&gt;
Для наилучшего решения этих проблем BIRCH распределяет входящие данные по кластерам динамически. Для эффективной кластеризации алгоритму требуется всего одно сканирование данных (т.е. с увеличением количества данных сложность увеличивается линейно). А при помощи одной (или более) дополнительных итераций можно и далее улучшать эффективность. BIRCH также является первым алгоритмом, предложенным для эффективного управления &amp;quot;шумами&amp;quot; (данными, которые не вписываются в общее представление модели).&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Теоретическая основа ===&lt;br /&gt;
&lt;br /&gt;
Пусть в кластере имеются &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}, i=1,2,...,N&amp;lt;/math&amp;gt;.&lt;br /&gt;
Тогда &#039;&#039;&#039;центроид&#039;&#039;&#039; &amp;lt;math&amp;gt;{\vec{{X_0}}}&amp;lt;/math&amp;gt;, &#039;&#039;&#039;радиус&#039;&#039;&#039; &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &#039;&#039;&#039;диаметр&#039;&#039;&#039; &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластера определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;{\vec{X_0}}=\frac{\sum_{i=1}^N\vec{X_i}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{\sum_{i=1}^N{(\vec{X_i} - \vec{X_0})}^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{\sum_{i=1}^N\sum_{j=1}^N{(\vec{X_i} - \vec{X_j})}^2}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; - это среднее расстояние от каждой точки до центроида. &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; - это среднее расстояние между парами в кластере. Данные величины являются альтернативными метриками плотности кластера относительно центроида.&lt;br /&gt;
&lt;br /&gt;
Для измерения близости друг к другу двух кластеров вводятся следующие метрики:&lt;br /&gt;
&lt;br /&gt;
пусть даны центроиды двух кластеров &amp;lt;math&amp;gt;\vec{X_{01}}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\vec{X_{02}}&amp;lt;/math&amp;gt;.&lt;br /&gt;
Евклидова метрика &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt; и метрика Манхэттена &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt; между двумя кластерами определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_0 = ((\vec{X_{01}}-\vec{X_{02}})^2)^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_1 = |\vec{X_{01}}-\vec{X_{02}}| = \sum_{i=1}^d |{\vec{X_{01}}}^{(i)}-{\vec{X_{02}}}^{(i)}| &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть имеются два кластера, содержащих соответственно  &amp;lt;math&amp;gt;N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;N_2&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i= 1,2, ...,N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\{\vec{X_j}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j= N_1+1,N_1+2, ...,N_1+N_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Среднее расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &#039;&#039;&#039;среднее внутрикластерное расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &#039;&#039;&#039;дисперсия&#039;&#039;&#039; &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; для двух кластеров определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{\sum_{i=1}^{N_1}\sum_{j=N_1+1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{N_1N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{\sum_{i=1}^{N_1+N_2}\sum_{j=1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_4 = \sum_{k=1}^{N_1+N_2}(\vec{X_k} - \frac{\sum_{i=1}^{N_1+N_2}\vec{X_i}}{N_1+N_2})^2 - \sum_{i=1}^{N_1}(\vec{X_i} - \frac{\sum_{i=1}^{N_1}\vec{X_i}}{N_1})^2 - \sum_{j=N_1+1}^{N_1+N_2}(\vec{X_j} - \frac{\sum_{i=N_1+1}^{N_1+N_2}\vec{X_i}}{N_2})^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Таким образом, величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; относятся к отдельным кластерам, а &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; - к объединению двух кластеров.&lt;br /&gt;
&lt;br /&gt;
=== Кластерный элемент и кластерное дерево ===&lt;br /&gt;
&lt;br /&gt;
В основе концепции алгоритма BIRCH лежат понятия &#039;&#039;&#039;кластерного элемента&#039;&#039;&#039; и &#039;&#039;&#039;кластерного дерева (CF Tree)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====Кластерный элемент ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; Пусть в кластере содержатся  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности  &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;:&amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;i=1,2,...,N&amp;lt;/math&amp;gt;. &lt;br /&gt;
&#039;&#039;&#039;Кластерный элемент (CF)&#039;&#039;&#039; - тройка чисел, характеризующая информацию о кластере: &lt;br /&gt;
&amp;lt;math&amp;gt;CF = (N, \vec{LS}, SS)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - количество элементов входных данных, содержащихся в кластере, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; - линейная сумма входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}\vec{X_i}&amp;lt;/math&amp;gt;), &amp;lt;math&amp;gt;SS&amp;lt;/math&amp;gt; - сумма квадратов входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}{\vec{X_i}}^2&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Теорема&#039;&#039;&#039; Пусть &amp;lt;math&amp;gt;CF_1 = (N_1, \vec{LS_1}, SS_1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;CF_2 = (N_1, \vec{LS_2}, SS_2)&amp;lt;/math&amp;gt; - CF векторы двух непересекающихся кластеров. Тогда при их объединении образуется кластер со следующим CF вектором: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF = CF_1 + CF_2 = (N_1+N_2, \vec{LS_1}+\vec{LS_2}, SS_1+SS_2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Из указанных выше определения и теоремы вытекает тот факт, что при объединении кластеров их CF вектор может вычисляться инкрементно и точно. &lt;br /&gt;
Легко показать, что вычислить величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;, как и обычные метрики, также не составит труда.&lt;br /&gt;
&lt;br /&gt;
Таким образом, в данном случае информацией о кластере является не весь набор точек, а вектор CF. Хранение одного только вектора может показаться неэффективным, но этого вполне достаточно для оперирования всеми необходимыми метриками, на основе которых принимаются решения в алгоритме BIRCH.&lt;br /&gt;
&lt;br /&gt;
==== Кластерное дерево ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; &#039;&#039;&#039;Кластерное дерево (CF Tree)&#039;&#039;&#039; - это взвешенно сбалансированное дерево с двумя параметрами: &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - коэффициент разветвления, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - пороговая величина.&lt;br /&gt;
&lt;br /&gt;
Каждый нелистьевой узел дерева имеет не более чем &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; вхождений узлов следующей формы: &amp;lt;math&amp;gt;[CF_i,child_i]&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i=1,2,...,B&amp;lt;/math&amp;gt;, &#039;&#039;child&#039;&#039; - указатель на i-й дочерний узел, &amp;lt;math&amp;gt;CF_i&amp;lt;/math&amp;gt; - CF вектор соответствующего подкластера.&lt;br /&gt;
&lt;br /&gt;
Каждый листьевой узел имеет ссылку на два соседних узла (&#039;&#039;prev&#039;&#039; и &#039;&#039;next&#039;&#039;) для того, чтобы связать все узлы для эффективного сканирования.&lt;br /&gt;
Все листьевые узлы должны удовлетворять пороговому ограничению &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, т.е. диаметр (радиус) не должен превосходить &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;.&lt;br /&gt;
В процессе вставки новых данных CF дерево строится динамически. Оно использует вставку данных для кластеризации точно также как &amp;lt;math&amp;gt;B+&amp;lt;/math&amp;gt; [https://ru.wikipedia.org/wiki/B%2B-%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE дерево] использует её для поиска.&lt;br /&gt;
CF дерево очень компактно, поскольку каждый листьевой узел - это не просто точка, а подкластер (который объединяет множество точек с учётом ограничения &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Операция вставки в &#039;&#039;&#039;CF&#039;&#039;&#039; дерево ====&lt;br /&gt;
&lt;br /&gt;
Опишем алгоритм вставки элемнта &amp;lt;math&amp;gt;Ent&amp;lt;/math&amp;gt; в CF дерево:&lt;br /&gt;
&lt;br /&gt;
1) &#039;&#039;Определение подходящего листа&#039;&#039;: Начиная с корня, алгоритм рекурсивно спускается по CF дереву, выбирая &#039;&#039;&#039;ближайший&#039;&#039;&#039; дочерний узел в соответствии с выбранной метрикой &amp;lt;math&amp;gt;D0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D4&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &#039;&#039;Преобразование листа&#039;&#039;: Когда алгоритм доходит до листа, он находит ближайшую листьевой элемент, скажем, &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;, а затем проверяет, можно ли добавить &#039;&#039;Ent&#039;&#039; к &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt; без нарушения порогового условия. Если да, то с учётом этого изменяется CF вектор для &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;; если нет, то &#039;&#039;Ent&#039;&#039; становится новым элементом листа. Если в листе для этого достаточно места, то шаг окончен, иначе он должен &amp;quot;расщепиться&amp;quot;. Расщепление узла производится при помощи выбора за основу наиболее удалённой друг от друга пары элементов и перераспределение оставшихся элементов в соответствии с выбранным критерием близости.&lt;br /&gt;
&lt;br /&gt;
3) &#039;&#039;Преобразование пути к листу&#039;&#039;: После вставки &#039;&#039;Ent&#039;&#039; в лист мы должны обновить информацию о CF для каждого нелистьевого элемента на пути к листу. При отсутствии расщепления это означает простое сложение CF векторов для отражения факта добавления &#039;&#039;Ent&#039;&#039;. Расщепление листа же требует вставки нового нелистьевого элемента в родительский узел для задания только что созданного листа. Если у родителя есть место для этого элемента, то необходимо просто преобразовать CF векторы на всех более высоких уровнях. В общем случае, однако, нам также придётся расщепить родительский узел, и так далее до корня. Если расщеплён корень, то высота дерева увеличивается на единицу.&lt;br /&gt;
&lt;br /&gt;
4) &#039;&#039;Улучшение слияния&#039;&#039;: Расщепление вызвано ограничением на размер узла, который не зависит от кластеризационных свойств данных. Если во входящем потоке присутствуют &amp;quot;искажённые&amp;quot; (из областей с низкой плотностью) данные, это может повлиять на качество кластеризации, а также уменьшить эффективность использования памяти. Дополнительный шаг алгоритма помогает решить эти проблемы: предположим, что произошло расщепление листа, и распространение этого процесса остановилось на некотором нелистьевом узле &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt;, то есть &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; может вместить дополнительный элемент, полученный после расщепления. Теперь мы сканируем узел &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; для нахождения двух наиболее близких элементов. Если это не пара, отвечающая расщеплению, мы пытаемся объединить их и поставить в соответствие два дочерних узла. Если количество элементов в дочерних узлах  больше B, мы снова расщепляем результат объединения.&lt;br /&gt;
В процессе повторного расщепления, в случае, если один источник собирает достаточно элементов для того, чтобы полностью заполнить узел, оставшиеся элементы передаются другом источнику. В итоге, если объединённые элементы помещаются в одном узле, в нём освобождается место для ещё одного элемента. Тем самым увеличивается степень использования свободного пространства и откладывается дальнейшее расщепление. В ином случае мы улучшаем распределение элементов в двух ближайших подкластерах.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро алгоритма заключается в многократном выполнении операции вставки нового элемента в дерево, в процессе чего требуется вычисление следующих величин:&lt;br /&gt;
&lt;br /&gt;
* радиуса &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; или диаметра &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластерного элемента. Выполняется при попытке вставить новый элемент в один из подкластеров листьевого узла дерева.&lt;br /&gt;
&lt;br /&gt;
* расстояния между двумя элементами. Выполняется при поиске ближайшего по отношению к новому элементу подкластера в узле дерева по одной из рассмотренных в разд. 1.2.1 метрик &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Зная характеристики кластерных элементов &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;, в результате алгебраических преобразований можно получить следующие упрощенные формулы вычисления необходимых значений:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\vec{X_0} = \frac{\vec{LS}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{SS - 2\vec{X_0}\vec{LS} + N(\vec{X_0})^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{2(N*SS - (\vec{LS})^2)}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{N_1*SS_2 + N_2*SS_1 - 2\vec{LS_1}\vec{LS_2}}{N_1*N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{2((N_1+N_2)(SS_1+SS_2)-(\vec{LS_1}+\vec{LS_2})^2)}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Реализация алгоритма BIRCH состояит из следующих четырёх фаз:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 1&#039;&#039;&#039;. Главной задачей фазы 1 является сканирование всех данных и построение в памяти исходного CF дерева, используя заданное количество памяти. Это дерево стремится отразить информацию о кластеризации данных настолько хорошо, насколько это позволяют ограничения по памяти. При этом плотно распределённые данные группируются в подкластеры, а более разрозненные данные удаляются. После завершения фазы 1 вспомогательные вычисления в дальнейших фазах будут:&lt;br /&gt;
&lt;br /&gt;
1) быстрее, потому что (а) больше не нужны операции ввода-вывода, (b) проблема кластеризации начальных данных упрощается до проблемы кластеризации подкластеров в листьях;&lt;br /&gt;
&lt;br /&gt;
2) точнее, потому что (а) большинство данных с низкой плотностью удалены, (b) оставшиеся данные распределены оптимально (в соответствии с доступным количеством памяти);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 2&#039;&#039;&#039;. Данная фаза является опциональной. Известно, что существующие методы глобальной кластеризации, используемые в рамках фазы 3, имеют различные диапазоны входных значений, при которых их реализация наиболее эффективна. Поэтому потенциально существует пробел между размером фазы 1 и входными значениями фазы 3. И фаза 2 как раз является недостающим связующим звеном: так же как и фаза 1, она сканирует листьевые элементы начального CF дерева для того, чтобы построить меньшее дерево, удаляя ещё больше элементов с низкой плотностью и группируя переполненные подкластеры в большие кластеры.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 3&#039;&#039;&#039;. В данной фазе для листьевых элементов применяется (любой подходящий) алгоритм глобальной кластеризации. Существующие алгоритмы кластеризации наборов точек могут также работать с наборами подкластеров, каждый из которых представлен своим CF вектором. Зная CF вектор, можно вычислить центроид и в дальнейшем заменить всю информацию о кластере этим значением (этого достаточно для вычисления большинства необходимых метрик). После фазы 3 мы получаем набор кластеров, который отражает основные характеристики распределяемых данных.&lt;br /&gt;
Однако, всё ещё могут оставаться некоторые неточности, для устранения которых существует фаза 4.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 4&#039;&#039;&#039;. Данная фаза является опциональной и влечёт за собой затраты на дополнительное сканирование данных для корректировки неточностей и дальнейшего улучшения кластеризации. Фаза 4 использует центроиды кластеров, полученные в фазе 3 для как основы и перераспределяет точки входных данных в ближайшие для них основы для получения нового списка кластеров. Фаза 4, если это необходимо пользователю, может быть расширена дополнительными проходами для уверенности в том, что результат приближается к оптимальному.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Последовательную реализацию основных операций алгоритма BIRCH можно продемонстрировать на примере следующего фрагмента кода на языке C++:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot;&amp;gt;&lt;br /&gt;
void CF_Node::insert(const CF_Cluster &amp;amp;entry)&lt;br /&gt;
{&lt;br /&gt;
    //Находим ближайший к новому элементу подкластер в узле&lt;br /&gt;
    СF_Vector_it closest = entry.findClosest(subclusters);&lt;br /&gt;
    //Если узел пустой, добавляем в него новый подкластер&lt;br /&gt;
    if (closest == subclusters.end()) {&lt;br /&gt;
        subclusters.push_back(entry);&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    closest-&amp;gt;add(entry);&lt;br /&gt;
    //Если узел является листьевым, и ближайший подкластер не может вместить&lt;br /&gt;
    //новый элемент, добавляем в узел новый подкластер&lt;br /&gt;
    if (leaf) {&lt;br /&gt;
        if (closest-&amp;gt;D &amp;gt; threshold) {&lt;br /&gt;
            closest-&amp;gt;remove(entry);&lt;br /&gt;
            subclusters.push_back(entry);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else {&lt;br /&gt;
        CF_Node *node = closest-&amp;gt;child;&lt;br /&gt;
        node-&amp;gt;insert(entry);&lt;br /&gt;
        //Если при добавлении нового элемента в дочерний узел тот переполнился,&lt;br /&gt;
        //расщепляем его        &lt;br /&gt;
        if (node-&amp;gt;getSubclusters().size() &amp;gt; bFactor) {&lt;br /&gt;
            CF_Vector newClusters = node-&amp;gt;splitNode();&lt;br /&gt;
            delete node;&lt;br /&gt;
            subclusters.erase(closest);&lt;br /&gt;
            subclusters.insert(subclusters.end(), newClusters.begin(), newClusters.end());&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    //Если узел является корневым и он переполнен, расщепляем его&lt;br /&gt;
    if (root &amp;amp;&amp;amp; subclusters.size() &amp;gt; bFactor) {&lt;br /&gt;
        subclusters = splitNode();&lt;br /&gt;
        leaf = false;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
CF_Vector CF_Node::splitNode()&lt;br /&gt;
{&lt;br /&gt;
    if (subclusters.size() &amp;lt; 2)&lt;br /&gt;
        return (root) ? subclusters : CF_Vector{CF_Cluster(this)};&lt;br /&gt;
    //Находим пару наиболее удаленных друг от друга подкластеров&lt;br /&gt;
    CF_Vector_it pole1, pole2;&lt;br /&gt;
    data_t longestDist = 0.0;&lt;br /&gt;
    for (auto lhs = subclusters.begin(); lhs != subclusters.end() - 1; ++lhs) {&lt;br /&gt;
        for (auto rhs = lhs + 1; rhs != subclusters.end(); ++rhs) {&lt;br /&gt;
            auto distance = getDistance(*lhs, *rhs);&lt;br /&gt;
            if (distance &amp;gt; longestDist) {&lt;br /&gt;
                longestDist = distance;&lt;br /&gt;
                pole1 = lhs;&lt;br /&gt;
                pole2 = rhs;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    //Разделяем множество всех подкластеров узла на две части&lt;br /&gt;
    CF_Vector subclusters1, subclusters2;&lt;br /&gt;
    for (auto it = subclusters.begin(); it != subclusters.end(); ++it) {&lt;br /&gt;
        if (getDistance(*it, *pole1) &amp;lt; getDistance(*it, *pole2))&lt;br /&gt;
            subclusters1.push_back(*it);&lt;br /&gt;
        else&lt;br /&gt;
            subclusters2.push_back(*it);&lt;br /&gt;
    }&lt;br /&gt;
    //Создаем два новых узла&lt;br /&gt;
    CF_Node *node1 = new CF_Node(threshold, bFactor, count, leaf, subclusters1),&lt;br /&gt;
            *node2 = new CF_Node(threshold, bFactor, count, leaf, subclusters2);&lt;br /&gt;
    //Связываем листья&lt;br /&gt;
    if (leaf) {&lt;br /&gt;
        if (prevLeaf) {&lt;br /&gt;
            node1-&amp;gt;setPrevLeaf(prevLeaf);&lt;br /&gt;
            prevLeaf-&amp;gt;setNextLeaf(node1);&lt;br /&gt;
        }&lt;br /&gt;
        if (nextLeaf) {&lt;br /&gt;
            node2-&amp;gt;setNextLeaf(nextLeaf);&lt;br /&gt;
            nextLeaf-&amp;gt;setPrevLeaf(node2);&lt;br /&gt;
        }&lt;br /&gt;
        node1-&amp;gt;setNextLeaf(node2);&lt;br /&gt;
        node2-&amp;gt;setPrevLeaf(node1);&lt;br /&gt;
    }&lt;br /&gt;
    CF_Cluster cluster1(node1), cluster2(node2);&lt;br /&gt;
    return CF_Vector{cluster1, cluster2};&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Для начала проанализируем вычислительную сложность фазы 1.&lt;br /&gt;
Максимальный размер дерева &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt; - ограничение по памяти на размер узла, а &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - общий объем памяти. Для того чтобы вставить элемент, мы должны пройти путь от корня до листа (это около &amp;lt;math&amp;gt;1+log_B\frac{M}{P}&amp;lt;/math&amp;gt; узлов). В каждом узле в поисках &amp;quot;ближайшего&amp;quot; нам необходимо просмотреть B элементов; сложность для каждого элемента пропорциональна размерности &#039;&#039;d&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Поэтому сложность вставки всех входных точек &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В случае, когда необходимо перестроить дерево, предположим, что ES - это размер CF элемента. Существует максимум &amp;lt;math&amp;gt;\frac{M}{ES}&amp;lt;/math&amp;gt; листьевых элементов для вставки, поэтому сложность повторной вставки листьевых элементов &amp;lt;math&amp;gt;O(d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Количество итераций перестройки дерева зависит от пороговой величины. На самом деле, это около &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; (двоичное основание появилось из-за того, что мы не можем провести оценку более чем в 2 раза отличающуюся от текущего размера). &amp;lt;math&amp;gt;N_0&amp;lt;/math&amp;gt; - это число входных точек, загруженных в память с пороговым ограничением &amp;lt;math&amp;gt;T_0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Соответственно, итоговая сложность фазы 1 &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P})+log_2\frac{N}{N_0}*d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Анализ фазы 2 проводится аналогично.&lt;br /&gt;
&lt;br /&gt;
Что касается операций ввода-вывода, то в фазе 1 данные сканируются один раз, а в фазе 2 не сканируются вовсе.&lt;br /&gt;
Некоторое количество вычислений связано с удалением точек из областей с низкой плотностью.&lt;br /&gt;
Если количество доступной для этой операции памяти не больше &#039;&#039;M&#039;&#039; и проведено порядка &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; перестроек дерева, то сложность ввода-вывода для фазы 1 существенно не отличается от сложности чтения из файла. Основываясь рассуждениях выше, сложность фаз 1 и 2 будет линейно увеличиваться с ростом N.&lt;br /&gt;
&lt;br /&gt;
В фазе 3 нет операций ввода-вывода. Её сложность ограничена константой, которая зависит от максимального размера входных данных, и варианта выбранного алгоритма для кластеризации. &lt;br /&gt;
&lt;br /&gt;
Фаза 4 снова сканирует данные и записывает каждую точку в подходящий кластер; время работы пропорционально &amp;lt;math&amp;gt;N*K&amp;lt;/math&amp;gt;.   &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
=== Вычисление расстояния ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2=\frac{N_1*SS_2+N_2*SS_1-2*\vec{LS_1}*\vec{LS_2}}{N_1*N_2}&amp;lt;/math&amp;gt;, где&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF_1=[N_1,\vec{LS_1},SS_1]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF_2=[N_2,\vec{LS_2},SS_2]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:ZgYL51QJsQk.jpg|500px|thumb|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Поиск ближайшего подкластера ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;E&amp;lt;/math&amp;gt; - новый элемент&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF_i, i = 1,...,B&amp;lt;/math&amp;gt; - подкластеры узла&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - операция min&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\rho&amp;lt;/math&amp;gt; - нахождение расстояния&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:PFA16KHUQ3I.jpg|500px|thumb|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельно могут быть выполнены следующие шаги алгоритма:&lt;br /&gt;
* Нахождение ближайшего к новому элементу подкластера в узле при выполнении операции вставки. Это возможно за счет того, что расстояние между парами элементов может быть вычислено независимо друг от друга. Сложность &lt;br /&gt;
* Вычисление величин &amp;lt;math&amp;gt;\vec{LS},\vec{X0}, R, D, D_0-D_4&amp;lt;/math&amp;gt;, в процессе чего выполняются операции сложения и скалярного произведения векторов.&lt;br /&gt;
&lt;br /&gt;
Другим способом параллелизации алгоритма может служить создание и заполнение сразу множества кластерных деревьев, между которыми будут распределены входные данные. Множество всех подкластеров листьевых узлов полученных таким образом деревьев может быть подвергнуто глобальной кластеризации с помощью какого-либо из известных параллельных алгоритмов, например, k-средних&amp;lt;ref&amp;gt;[http://people.du.ac.in/~ngupta/Publications/PBIRCH%20A%20Sacalabel%20Paralllel%20Clustering.pdf A Garg, N Gupta PBIRCH: A Scalable Parallel Clustering algorithm for Incremental Data]&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;
* Набор из &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек &amp;lt;math&amp;gt;\{X_i\}, i=1,...,N&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Кластерное дерево с не более чем &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt; узлами.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Достоинства алгоритма ===&lt;br /&gt;
По сравнению с предыдущими методами BIRCH обладает следующими достоинствами:&lt;br /&gt;
&lt;br /&gt;
1. BIRCH является локальным алгоритмом, то есть каждое решение о каждом элементе кластера принимается без повторного сканирования данных или уже существующих кластеров. Используются только метрики, отражающие близость элементов друг к другу.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH использует факт неравномерного распределения данных в пространстве и поэтому не все данные рассматриваются как одинаково важные для построения кластера. Области с большой плотностью обрабатываются как единый кластер. Данные в более разреженных областях могут удаляться (опционально).&lt;br /&gt;
&lt;br /&gt;
3. BIRCH использует всю доступную память для получения наилучших из возможных подкластеров, в то же время минимизируя затраты на операции ввода/вывода. Оптимизация процесса кластеризации достигается за счет использования взвешенно-сбалансированного дерева. При этом время исполнения линейно.&lt;br /&gt;
&lt;br /&gt;
4. BIRCH не требует всего набора данных заранее (при этом просматривает его всего один раз).&lt;br /&gt;
&lt;br /&gt;
=== Недостатки алгоритма ===&lt;br /&gt;
&lt;br /&gt;
1. Алгоритм позволяет работать только с числовыми данными.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH хорошо выделяет только кластеры сферической формы.&lt;br /&gt;
&lt;br /&gt;
3. Существует необходимость в задании пороговых значений.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
В составе пакетов и библиотек:&lt;br /&gt;
* [http://scikit-learn.org/stable/modules/generated/sklearn.cluster.Birch.html scikit-learn]&lt;br /&gt;
* [http://cucis.ece.northwestern.edu/projects/DMS/MineBench.html NU-MineBench]&lt;br /&gt;
Пользовательские реализации:&lt;br /&gt;
* [https://code.google.com/archive/p/jbirch/ JBIRCH]&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Светлана Морозова</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13840</id>
		<title>Участник:Smirnov.maxim/BIRCH</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13840"/>
		<updated>2016-10-26T07:31:15Z</updated>

		<summary type="html">&lt;p&gt;Светлана Морозова: /* Информационный граф */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Авторы: [[Участник:Светлана Морозова|Морозова Светлана]], [[Участник:Smirnov.maxim|Смирнов Максим]].&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Нахождение полезных для анализа закономерностей в больших объёмах данных с недавних пор вызывает значительный интерес. В связи с этим ввелось и стало активно развиваться такое понятие как &#039;&#039;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7 кластеризация]&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Ранние работы и алгоритмы, разработанные в этой области, не уделяли достаточного внимания анализу очень больших наборов данных или минимизации издержек на процессы ввода-вывода.&lt;br /&gt;
Решением этих проблем стал алгоритм, известный как BIRCH.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIRCH&#039;&#039;&#039;&amp;lt;ref&amp;gt;[http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf Нейский И.М. Классификация и сравнение методов кластеризации]&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;[http://www.cs.sfu.ca/CourseCentral/459/han/papers/zhang96.pdf T Zhang, R Ramakrishnan, M Livny. BIRCH: An Efficient Data Clustering Method for Very Large Databases]&amp;lt;/ref&amp;gt; (balanced iterative reducing and clustering using hierarchies)- алгоритм, применяемый в области [https://ru.wikipedia.org/wiki/Data_mining Data mining] и использующий принципы [https://ru.wikipedia.org/wiki/%D0%98%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F иерархической кластеризации].&lt;br /&gt;
&lt;br /&gt;
Если имеется очень большой набор данных, то в пространстве он распределен, как правило, неравномерно. Кластерный анализ определяет места наибольшего и наименьшего скоплений, чтобы таким образом понять всю картину целиком. Кроме того, полученные кластеры визуализируются гораздо нагляднее, чем начальные &amp;quot;сырые&amp;quot; данные.&lt;br /&gt;
Задачей алгоритмов кластеризации является не только простое разбиение данных на кластеры, но и работа в рамках ограниченного объёма доступной памяти (как правило, её объём гораздо меньше, чем размер исходного набора данных) и минимизация времени, требуемого на операции ввода-вывода.&lt;br /&gt;
&lt;br /&gt;
Для наилучшего решения этих проблем BIRCH распределяет входящие данные по кластерам динамически. Для эффективной кластеризации алгоритму требуется всего одно сканирование данных (т.е. с увеличением количества данных сложность увеличивается линейно). А при помощи одной (или более) дополнительных итераций можно и далее улучшать эффективность. BIRCH также является первым алгоритмом, предложенным для эффективного управления &amp;quot;шумами&amp;quot; (данными, которые не вписываются в общее представление модели).&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Теоретическая основа ===&lt;br /&gt;
&lt;br /&gt;
Пусть в кластере имеются &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}, i=1,2,...,N&amp;lt;/math&amp;gt;.&lt;br /&gt;
Тогда &#039;&#039;&#039;центроид&#039;&#039;&#039; &amp;lt;math&amp;gt;{\vec{{X_0}}}&amp;lt;/math&amp;gt;, &#039;&#039;&#039;радиус&#039;&#039;&#039; &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &#039;&#039;&#039;диаметр&#039;&#039;&#039; &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластера определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;{\vec{X_0}}=\frac{\sum_{i=1}^N\vec{X_i}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{\sum_{i=1}^N{(\vec{X_i} - \vec{X_0})}^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{\sum_{i=1}^N\sum_{j=1}^N{(\vec{X_i} - \vec{X_j})}^2}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; - это среднее расстояние от каждой точки до центроида. &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; - это среднее расстояние между парами в кластере. Данные величины являются альтернативными метриками плотности кластера относительно центроида.&lt;br /&gt;
&lt;br /&gt;
Для измерения близости друг к другу двух кластеров вводятся следующие метрики:&lt;br /&gt;
&lt;br /&gt;
пусть даны центроиды двух кластеров &amp;lt;math&amp;gt;\vec{X_{01}}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\vec{X_{02}}&amp;lt;/math&amp;gt;.&lt;br /&gt;
Евклидова метрика &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt; и метрика Манхэттена &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt; между двумя кластерами определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_0 = ((\vec{X_{01}}-\vec{X_{02}})^2)^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_1 = |\vec{X_{01}}-\vec{X_{02}}| = \sum_{i=1}^d |{\vec{X_{01}}}^{(i)}-{\vec{X_{02}}}^{(i)}| &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть имеются два кластера, содержащих соответственно  &amp;lt;math&amp;gt;N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;N_2&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i= 1,2, ...,N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\{\vec{X_j}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j= N_1+1,N_1+2, ...,N_1+N_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Среднее расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &#039;&#039;&#039;среднее внутрикластерное расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &#039;&#039;&#039;дисперсия&#039;&#039;&#039; &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; для двух кластеров определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{\sum_{i=1}^{N_1}\sum_{j=N_1+1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{N_1N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{\sum_{i=1}^{N_1+N_2}\sum_{j=1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_4 = \sum_{k=1}^{N_1+N_2}(\vec{X_k} - \frac{\sum_{i=1}^{N_1+N_2}\vec{X_i}}{N_1+N_2})^2 - \sum_{i=1}^{N_1}(\vec{X_i} - \frac{\sum_{i=1}^{N_1}\vec{X_i}}{N_1})^2 - \sum_{j=N_1+1}^{N_1+N_2}(\vec{X_j} - \frac{\sum_{i=N_1+1}^{N_1+N_2}\vec{X_i}}{N_2})^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Таким образом, величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; относятся к отдельным кластерам, а &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; - к объединению двух кластеров.&lt;br /&gt;
&lt;br /&gt;
=== Кластерный элемент и кластерное дерево ===&lt;br /&gt;
&lt;br /&gt;
В основе концепции алгоритма BIRCH лежат понятия &#039;&#039;&#039;кластерного элемента&#039;&#039;&#039; и &#039;&#039;&#039;кластерного дерева (CF Tree)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====Кластерный элемент ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; Пусть в кластере содержатся  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности  &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;:&amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;i=1,2,...,N&amp;lt;/math&amp;gt;. &lt;br /&gt;
&#039;&#039;&#039;Кластерный элемент (CF)&#039;&#039;&#039; - тройка чисел, характеризующая информацию о кластере: &lt;br /&gt;
&amp;lt;math&amp;gt;CF = (N, \vec{LS}, SS)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - количество элементов входных данных, содержащихся в кластере, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; - линейная сумма входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}\vec{X_i}&amp;lt;/math&amp;gt;), &amp;lt;math&amp;gt;SS&amp;lt;/math&amp;gt; - сумма квадратов входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}{\vec{X_i}}^2&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Теорема&#039;&#039;&#039; Пусть &amp;lt;math&amp;gt;CF_1 = (N_1, \vec{LS_1}, SS_1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;CF_2 = (N_1, \vec{LS_2}, SS_2)&amp;lt;/math&amp;gt; - CF векторы двух непересекающихся кластеров. Тогда при их объединении образуется кластер со следующим CF вектором: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF = CF_1 + CF_2 = (N_1+N_2, \vec{LS_1}+\vec{LS_2}, SS_1+SS_2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Из указанных выше определения и теоремы вытекает тот факт, что при объединении кластеров их CF вектор может вычисляться инкрементно и точно. &lt;br /&gt;
Легко показать, что вычислить величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;, как и обычные метрики, также не составит труда.&lt;br /&gt;
&lt;br /&gt;
Таким образом, в данном случае информацией о кластере является не весь набор точек, а вектор CF. Хранение одного только вектора может показаться неэффективным, но этого вполне достаточно для оперирования всеми необходимыми метриками, на основе которых принимаются решения в алгоритме BIRCH.&lt;br /&gt;
&lt;br /&gt;
==== Кластерное дерево ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; &#039;&#039;&#039;Кластерное дерево (CF Tree)&#039;&#039;&#039; - это взвешенно сбалансированное дерево с двумя параметрами: &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - коэффициент разветвления, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - пороговая величина.&lt;br /&gt;
&lt;br /&gt;
Каждый нелистьевой узел дерева имеет не более чем &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; вхождений узлов следующей формы: &amp;lt;math&amp;gt;[CF_i,child_i]&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i=1,2,...,B&amp;lt;/math&amp;gt;, &#039;&#039;child&#039;&#039; - указатель на i-й дочерний узел, &amp;lt;math&amp;gt;CF_i&amp;lt;/math&amp;gt; - CF вектор соответствующего подкластера.&lt;br /&gt;
&lt;br /&gt;
Каждый листьевой узел имеет ссылку на два соседних узла (&#039;&#039;prev&#039;&#039; и &#039;&#039;next&#039;&#039;) для того, чтобы связать все узлы для эффективного сканирования.&lt;br /&gt;
Все листьевые узлы должны удовлетворять пороговому ограничению &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, т.е. диаметр (радиус) не должен превосходить &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;.&lt;br /&gt;
В процессе вставки новых данных CF дерево строится динамически. Оно использует вставку данных для кластеризации точно также как &amp;lt;math&amp;gt;B+&amp;lt;/math&amp;gt; [https://ru.wikipedia.org/wiki/B%2B-%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE дерево] использует её для поиска.&lt;br /&gt;
CF дерево очень компактно, поскольку каждый листьевой узел - это не просто точка, а подкластер (который объединяет множество точек с учётом ограничения &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Операция вставки в &#039;&#039;&#039;CF&#039;&#039;&#039; дерево ====&lt;br /&gt;
&lt;br /&gt;
Опишем алгоритм вставки элемнта &amp;lt;math&amp;gt;Ent&amp;lt;/math&amp;gt; в CF дерево:&lt;br /&gt;
&lt;br /&gt;
1) &#039;&#039;Определение подходящего листа&#039;&#039;: Начиная с корня, алгоритм рекурсивно спускается по CF дереву, выбирая &#039;&#039;&#039;ближайший&#039;&#039;&#039; дочерний узел в соответствии с выбранной метрикой &amp;lt;math&amp;gt;D0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D4&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &#039;&#039;Преобразование листа&#039;&#039;: Когда алгоритм доходит до листа, он находит ближайшую листьевой элемент, скажем, &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;, а затем проверяет, можно ли добавить &#039;&#039;Ent&#039;&#039; к &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt; без нарушения порогового условия. Если да, то с учётом этого изменяется CF вектор для &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;; если нет, то &#039;&#039;Ent&#039;&#039; становится новым элементом листа. Если в листе для этого достаточно места, то шаг окончен, иначе он должен &amp;quot;расщепиться&amp;quot;. Расщепление узла производится при помощи выбора за основу наиболее удалённой друг от друга пары элементов и перераспределение оставшихся элементов в соответствии с выбранным критерием близости.&lt;br /&gt;
&lt;br /&gt;
3) &#039;&#039;Преобразование пути к листу&#039;&#039;: После вставки &#039;&#039;Ent&#039;&#039; в лист мы должны обновить информацию о CF для каждого нелистьевого элемента на пути к листу. При отсутствии расщепления это означает простое сложение CF векторов для отражения факта добавления &#039;&#039;Ent&#039;&#039;. Расщепление листа же требует вставки нового нелистьевого элемента в родительский узел для задания только что созданного листа. Если у родителя есть место для этого элемента, то необходимо просто преобразовать CF векторы на всех более высоких уровнях. В общем случае, однако, нам также придётся расщепить родительский узел, и так далее до корня. Если расщеплён корень, то высота дерева увеличивается на единицу.&lt;br /&gt;
&lt;br /&gt;
4) &#039;&#039;Улучшение слияния&#039;&#039;: Расщепление вызвано ограничением на размер узла, который не зависит от кластеризационных свойств данных. Если во входящем потоке присутствуют &amp;quot;искажённые&amp;quot; (из областей с низкой плотностью) данные, это может повлиять на качество кластеризации, а также уменьшить эффективность использования памяти. Дополнительный шаг алгоритма помогает решить эти проблемы: предположим, что произошло расщепление листа, и распространение этого процесса остановилось на некотором нелистьевом узле &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt;, то есть &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; может вместить дополнительный элемент, полученный после расщепления. Теперь мы сканируем узел &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; для нахождения двух наиболее близких элементов. Если это не пара, отвечающая расщеплению, мы пытаемся объединить их и поставить в соответствие два дочерних узла. Если количество элементов в дочерних узлах  больше B, мы снова расщепляем результат объединения.&lt;br /&gt;
В процессе повторного расщепления, в случае, если один источник собирает достаточно элементов для того, чтобы полностью заполнить узел, оставшиеся элементы передаются другом источнику. В итоге, если объединённые элементы помещаются в одном узле, в нём освобождается место для ещё одного элемента. Тем самым увеличивается степень использования свободного пространства и откладывается дальнейшее расщепление. В ином случае мы улучшаем распределение элементов в двух ближайших подкластерах.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро алгоритма заключается в многократном выполнении операции вставки нового элемента в дерево, в процессе чего требуется вычисление следующих величин:&lt;br /&gt;
&lt;br /&gt;
* радиуса &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; или диаметра &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластерного элемента. Выполняется при попытке вставить новый элемент в один из подкластеров листьевого узла дерева.&lt;br /&gt;
&lt;br /&gt;
* расстояния между двумя элементами. Выполняется при поиске ближайшего по отношению к новому элементу подкластера в узле дерева по одной из рассмотренных в разд. 1.2.1 метрик &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Зная характеристики кластерных элементов &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;, в результате алгебраических преобразований можно получить следующие упрощенные формулы вычисления необходимых значений:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\vec{X_0} = \frac{\vec{LS}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{SS - 2\vec{X_0}\vec{LS} + N(\vec{X_0})^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{2(N*SS - (\vec{LS})^2)}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{N_1*SS_2 + N_2*SS_1 - 2\vec{LS_1}\vec{LS_2}}{N_1*N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{2((N_1+N_2)(SS_1+SS_2)-(\vec{LS_1}+\vec{LS_2})^2)}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Реализация алгоритма BIRCH состояит из следующих четырёх фаз:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 1&#039;&#039;&#039;. Главной задачей фазы 1 является сканирование всех данных и построение в памяти исходного CF дерева, используя заданное количество памяти. Это дерево стремится отразить информацию о кластеризации данных настолько хорошо, насколько это позволяют ограничения по памяти. При этом плотно распределённые данные группируются в подкластеры, а более разрозненные данные удаляются. После завершения фазы 1 вспомогательные вычисления в дальнейших фазах будут:&lt;br /&gt;
&lt;br /&gt;
1) быстрее, потому что (а) больше не нужны операции ввода-вывода, (b) проблема кластеризации начальных данных упрощается до проблемы кластеризации подкластеров в листьях;&lt;br /&gt;
&lt;br /&gt;
2) точнее, потому что (а) большинство данных с низкой плотностью удалены, (b) оставшиеся данные распределены оптимально (в соответствии с доступным количеством памяти);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 2&#039;&#039;&#039;. Данная фаза является опциональной. Известно, что существующие методы глобальной кластеризации, используемые в рамках фазы 3, имеют различные диапазоны входных значений, при которых их реализация наиболее эффективна. Поэтому потенциально существует пробел между размером фазы 1 и входными значениями фазы 3. И фаза 2 как раз является недостающим связующим звеном: так же как и фаза 1, она сканирует листьевые элементы начального CF дерева для того, чтобы построить меньшее дерево, удаляя ещё больше элементов с низкой плотностью и группируя переполненные подкластеры в большие кластеры.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 3&#039;&#039;&#039;. В данной фазе для листьевых элементов применяется (любой подходящий) алгоритм глобальной кластеризации. Существующие алгоритмы кластеризации наборов точек могут также работать с наборами подкластеров, каждый из которых представлен своим CF вектором. Зная CF вектор, можно вычислить центроид и в дальнейшем заменить всю информацию о кластере этим значением (этого достаточно для вычисления большинства необходимых метрик). После фазы 3 мы получаем набор кластеров, который отражает основные характеристики распределяемых данных.&lt;br /&gt;
Однако, всё ещё могут оставаться некоторые неточности, для устранения которых существует фаза 4.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 4&#039;&#039;&#039;. Данная фаза является опциональной и влечёт за собой затраты на дополнительное сканирование данных для корректировки неточностей и дальнейшего улучшения кластеризации. Фаза 4 использует центроиды кластеров, полученные в фазе 3 для как основы и перераспределяет точки входных данных в ближайшие для них основы для получения нового списка кластеров. Фаза 4, если это необходимо пользователю, может быть расширена дополнительными проходами для уверенности в том, что результат приближается к оптимальному.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Последовательную реализацию основных операций алгоритма BIRCH можно продемонстрировать на примере следующего фрагмента кода на языке C++:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot;&amp;gt;&lt;br /&gt;
void CF_Node::insert(const CF_Cluster &amp;amp;entry)&lt;br /&gt;
{&lt;br /&gt;
    //Находим ближайший к новому элементу подкластер в узле&lt;br /&gt;
    СF_Vector_it closest = entry.findClosest(subclusters);&lt;br /&gt;
    //Если узел пустой, добавляем в него новый подкластер&lt;br /&gt;
    if (closest == subclusters.end()) {&lt;br /&gt;
        subclusters.push_back(entry);&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    closest-&amp;gt;add(entry);&lt;br /&gt;
    //Если узел является листьевым, и ближайший подкластер не может вместить&lt;br /&gt;
    //новый элемент, добавляем в узел новый подкластер&lt;br /&gt;
    if (leaf) {&lt;br /&gt;
        if (closest-&amp;gt;D &amp;gt; threshold) {&lt;br /&gt;
            closest-&amp;gt;remove(entry);&lt;br /&gt;
            subclusters.push_back(entry);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else {&lt;br /&gt;
        CF_Node *node = closest-&amp;gt;child;&lt;br /&gt;
        node-&amp;gt;insert(entry);&lt;br /&gt;
        //Если при добавлении нового элемента в дочерний узел тот переполнился,&lt;br /&gt;
        //расщепляем его        &lt;br /&gt;
        if (node-&amp;gt;getSubclusters().size() &amp;gt; bFactor) {&lt;br /&gt;
            CF_Vector newClusters = node-&amp;gt;splitNode();&lt;br /&gt;
            delete node;&lt;br /&gt;
            subclusters.erase(closest);&lt;br /&gt;
            subclusters.insert(subclusters.end(), newClusters.begin(), newClusters.end());&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    //Если узел является корневым и он переполнен, расщепляем его&lt;br /&gt;
    if (root &amp;amp;&amp;amp; subclusters.size() &amp;gt; bFactor) {&lt;br /&gt;
        subclusters = splitNode();&lt;br /&gt;
        leaf = false;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
CF_Vector CF_Node::splitNode()&lt;br /&gt;
{&lt;br /&gt;
    if (subclusters.size() &amp;lt; 2)&lt;br /&gt;
        return (root) ? subclusters : CF_Vector{CF_Cluster(this)};&lt;br /&gt;
    //Находим пару наиболее удаленных друг от друга подкластеров&lt;br /&gt;
    CF_Vector_it pole1, pole2;&lt;br /&gt;
    data_t longestDist = 0.0;&lt;br /&gt;
    for (auto lhs = subclusters.begin(); lhs != subclusters.end() - 1; ++lhs) {&lt;br /&gt;
        for (auto rhs = lhs + 1; rhs != subclusters.end(); ++rhs) {&lt;br /&gt;
            auto distance = getDistance(*lhs, *rhs);&lt;br /&gt;
            if (distance &amp;gt; longestDist) {&lt;br /&gt;
                longestDist = distance;&lt;br /&gt;
                pole1 = lhs;&lt;br /&gt;
                pole2 = rhs;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    //Разделяем множество всех подкластеров узла на две части&lt;br /&gt;
    CF_Vector subclusters1, subclusters2;&lt;br /&gt;
    for (auto it = subclusters.begin(); it != subclusters.end(); ++it) {&lt;br /&gt;
        if (getDistance(*it, *pole1) &amp;lt; getDistance(*it, *pole2))&lt;br /&gt;
            subclusters1.push_back(*it);&lt;br /&gt;
        else&lt;br /&gt;
            subclusters2.push_back(*it);&lt;br /&gt;
    }&lt;br /&gt;
    //Создаем два новых узла&lt;br /&gt;
    CF_Node *node1 = new CF_Node(threshold, bFactor, count, leaf, subclusters1),&lt;br /&gt;
            *node2 = new CF_Node(threshold, bFactor, count, leaf, subclusters2);&lt;br /&gt;
    //Связываем листья&lt;br /&gt;
    if (leaf) {&lt;br /&gt;
        if (prevLeaf) {&lt;br /&gt;
            node1-&amp;gt;setPrevLeaf(prevLeaf);&lt;br /&gt;
            prevLeaf-&amp;gt;setNextLeaf(node1);&lt;br /&gt;
        }&lt;br /&gt;
        if (nextLeaf) {&lt;br /&gt;
            node2-&amp;gt;setNextLeaf(nextLeaf);&lt;br /&gt;
            nextLeaf-&amp;gt;setPrevLeaf(node2);&lt;br /&gt;
        }&lt;br /&gt;
        node1-&amp;gt;setNextLeaf(node2);&lt;br /&gt;
        node2-&amp;gt;setPrevLeaf(node1);&lt;br /&gt;
    }&lt;br /&gt;
    CF_Cluster cluster1(node1), cluster2(node2);&lt;br /&gt;
    return CF_Vector{cluster1, cluster2};&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Для начала проанализируем вычислительную сложность фазы 1.&lt;br /&gt;
Максимальный размер дерева &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt; - ограничение по памяти на размер узла, а &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - общий объем памяти. Для того чтобы вставить элемент, мы должны пройти путь от корня до листа (это около &amp;lt;math&amp;gt;1+log_B\frac{M}{P}&amp;lt;/math&amp;gt; узлов). В каждом узле в поисках &amp;quot;ближайшего&amp;quot; нам необходимо просмотреть B элементов; сложность для каждого элемента пропорциональна размерности &#039;&#039;d&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Поэтому сложность вставки всех входных точек &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В случае, когда необходимо перестроить дерево, предположим, что ES - это размер CF элемента. Существует максимум &amp;lt;math&amp;gt;\frac{M}{ES}&amp;lt;/math&amp;gt; листьевых элементов для вставки, поэтому сложность повторной вставки листьевых элементов &amp;lt;math&amp;gt;O(d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Количество итераций перестройки дерева зависит от пороговой величины. На самом деле, это около &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; (двоичное основание появилось из-за того, что мы не можем провести оценку более чем в 2 раза отличающуюся от текущего размера). &amp;lt;math&amp;gt;N_0&amp;lt;/math&amp;gt; - это число входных точек, загруженных в память с пороговым ограничением &amp;lt;math&amp;gt;T_0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Соответственно, итоговая сложность фазы 1 &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P})+log_2\frac{N}{N_0}*d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Анализ фазы 2 проводится аналогично.&lt;br /&gt;
&lt;br /&gt;
Что касается операций ввода-вывода, то в фазе 1 данные сканируются один раз, а в фазе 2 не сканируются вовсе.&lt;br /&gt;
Некоторое количество вычислений связано с удалением точек из областей с низкой плотностью.&lt;br /&gt;
Если количество доступной для этой операции памяти не больше &#039;&#039;M&#039;&#039; и проведено порядка &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; перестроек дерева, то сложность ввода-вывода для фазы 1 существенно не отличается от сложности чтения из файла. Основываясь рассуждениях выше, сложность фаз 1 и 2 будет линейно увеличиваться с ростом N.&lt;br /&gt;
&lt;br /&gt;
В фазе 3 нет операций ввода-вывода. Её сложность ограничена константой, которая зависит от максимального размера входных данных, и варианта выбранного алгоритма для кластеризации. &lt;br /&gt;
&lt;br /&gt;
Фаза 4 снова сканирует данные и записывает каждую точку в подходящий кластер; время работы пропорционально &amp;lt;math&amp;gt;N*K&amp;lt;/math&amp;gt;.   &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
=== Вычисление расстояния ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2=\frac{N_1*SS_2+N_2*SS_1-2*\vec{LS_1}*\vec{LS_2}}{N_1*N_2}&amp;lt;/math&amp;gt;, где&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF_1=[N_1,\vec{LS_1},SS_1]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF_2=[N_2,\vec{LS_2},SS_2]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:ZgYL51QJsQk.jpg|500px|thumb|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Поиск ближайшего подкластера ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;E&amp;lt;/math&amp;gt; - новый элемент&lt;br /&gt;
&amp;lt;math&amp;gt;CF_i, i=1..B&amp;lt;/math&amp;gt; - подкластеры узла&lt;br /&gt;
&amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - операция min&lt;br /&gt;
&amp;lt;math&amp;gt;\ro&amp;lt;/math&amp;gt; - нахождение расстояния&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:PFA16KHUQ3I.jpg|500px|thumb|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельно могут быть выполнены следующие шаги алгоритма:&lt;br /&gt;
* Нахождение ближайшего к новому элементу подкластера в узле при выполнении операции вставки. Это возможно за счет того, что расстояние между парами элементов может быть вычислено независимо друг от друга. Сложность &lt;br /&gt;
* Вычисление величин &amp;lt;math&amp;gt;\vec{LS},\vec{X0}, R, D, D_0-D_4&amp;lt;/math&amp;gt;, в процессе чего выполняются операции сложения и скалярного произведения векторов.&lt;br /&gt;
&lt;br /&gt;
Другим способом параллелизации алгоритма может служить создание и заполнение сразу множества кластерных деревьев, между которыми будут распределены входные данные. Множество всех подкластеров листьевых узлов полученных таким образом деревьев может быть подвергнуто глобальной кластеризации с помощью какого-либо из известных параллельных алгоритмов, например, k-средних&amp;lt;ref&amp;gt;[http://people.du.ac.in/~ngupta/Publications/PBIRCH%20A%20Sacalabel%20Paralllel%20Clustering.pdf A Garg, N Gupta PBIRCH: A Scalable Parallel Clustering algorithm for Incremental Data]&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;
* Набор из &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек &amp;lt;math&amp;gt;\{X_i\}, i=1,...,N&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Кластерное дерево с не более чем &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt; узлами.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Достоинства алгоритма ===&lt;br /&gt;
По сравнению с предыдущими методами BIRCH обладает следующими достоинствами:&lt;br /&gt;
&lt;br /&gt;
1. BIRCH является локальным алгоритмом, то есть каждое решение о каждом элементе кластера принимается без повторного сканирования данных или уже существующих кластеров. Используются только метрики, отражающие близость элементов друг к другу.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH использует факт неравномерного распределения данных в пространстве и поэтому не все данные рассматриваются как одинаково важные для построения кластера. Области с большой плотностью обрабатываются как единый кластер. Данные в более разреженных областях могут удаляться (опционально).&lt;br /&gt;
&lt;br /&gt;
3. BIRCH использует всю доступную память для получения наилучших из возможных подкластеров, в то же время минимизируя затраты на операции ввода/вывода. Оптимизация процесса кластеризации достигается за счет использования взвешенно-сбалансированного дерева. При этом время исполнения линейно.&lt;br /&gt;
&lt;br /&gt;
4. BIRCH не требует всего набора данных заранее (при этом просматривает его всего один раз).&lt;br /&gt;
&lt;br /&gt;
=== Недостатки алгоритма ===&lt;br /&gt;
&lt;br /&gt;
1. Алгоритм позволяет работать только с числовыми данными.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH хорошо выделяет только кластеры сферической формы.&lt;br /&gt;
&lt;br /&gt;
3. Существует необходимость в задании пороговых значений.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
В составе пакетов и библиотек:&lt;br /&gt;
* [http://scikit-learn.org/stable/modules/generated/sklearn.cluster.Birch.html scikit-learn]&lt;br /&gt;
* [http://cucis.ece.northwestern.edu/projects/DMS/MineBench.html NU-MineBench]&lt;br /&gt;
Пользовательские реализации:&lt;br /&gt;
* [https://code.google.com/archive/p/jbirch/ JBIRCH]&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Светлана Морозова</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13837</id>
		<title>Участник:Smirnov.maxim/BIRCH</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13837"/>
		<updated>2016-10-26T07:27:16Z</updated>

		<summary type="html">&lt;p&gt;Светлана Морозова: /* Вычисление расстояния */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Авторы: [[Участник:Светлана Морозова|Морозова Светлана]], [[Участник:Smirnov.maxim|Смирнов Максим]].&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Нахождение полезных для анализа закономерностей в больших объёмах данных с недавних пор вызывает значительный интерес. В связи с этим ввелось и стало активно развиваться такое понятие как &#039;&#039;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7 кластеризация]&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Ранние работы и алгоритмы, разработанные в этой области, не уделяли достаточного внимания анализу очень больших наборов данных или минимизации издержек на процессы ввода-вывода.&lt;br /&gt;
Решением этих проблем стал алгоритм, известный как BIRCH.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIRCH&#039;&#039;&#039;&amp;lt;ref&amp;gt;[http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf Нейский И.М. Классификация и сравнение методов кластеризации]&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;[http://www.cs.sfu.ca/CourseCentral/459/han/papers/zhang96.pdf T Zhang, R Ramakrishnan, M Livny. BIRCH: An Efficient Data Clustering Method for Very Large Databases]&amp;lt;/ref&amp;gt; (balanced iterative reducing and clustering using hierarchies)- алгоритм, применяемый в области [https://ru.wikipedia.org/wiki/Data_mining Data mining] и использующий принципы [https://ru.wikipedia.org/wiki/%D0%98%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F иерархической кластеризации].&lt;br /&gt;
&lt;br /&gt;
Если имеется очень большой набор данных, то в пространстве он распределен, как правило, неравномерно. Кластерный анализ определяет места наибольшего и наименьшего скоплений, чтобы таким образом понять всю картину целиком. Кроме того, полученные кластеры визуализируются гораздо нагляднее, чем начальные &amp;quot;сырые&amp;quot; данные.&lt;br /&gt;
Задачей алгоритмов кластеризации является не только простое разбиение данных на кластеры, но и работа в рамках ограниченного объёма доступной памяти (как правило, её объём гораздо меньше, чем размер исходного набора данных) и минимизация времени, требуемого на операции ввода-вывода.&lt;br /&gt;
&lt;br /&gt;
Для наилучшего решения этих проблем BIRCH распределяет входящие данные по кластерам динамически. Для эффективной кластеризации алгоритму требуется всего одно сканирование данных (т.е. с увеличением количества данных сложность увеличивается линейно). А при помощи одной (или более) дополнительных итераций можно и далее улучшать эффективность. BIRCH также является первым алгоритмом, предложенным для эффективного управления &amp;quot;шумами&amp;quot; (данными, которые не вписываются в общее представление модели).&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Теоретическая основа ===&lt;br /&gt;
&lt;br /&gt;
Пусть в кластере имеются &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}, i=1,2,...,N&amp;lt;/math&amp;gt;.&lt;br /&gt;
Тогда &#039;&#039;&#039;центроид&#039;&#039;&#039; &amp;lt;math&amp;gt;{\vec{{X_0}}}&amp;lt;/math&amp;gt;, &#039;&#039;&#039;радиус&#039;&#039;&#039; &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &#039;&#039;&#039;диаметр&#039;&#039;&#039; &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластера определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;{\vec{X_0}}=\frac{\sum_{i=1}^N\vec{X_i}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{\sum_{i=1}^N{(\vec{X_i} - \vec{X_0})}^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{\sum_{i=1}^N\sum_{j=1}^N{(\vec{X_i} - \vec{X_j})}^2}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; - это среднее расстояние от каждой точки до центроида. &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; - это среднее расстояние между парами в кластере. Данные величины являются альтернативными метриками плотности кластера относительно центроида.&lt;br /&gt;
&lt;br /&gt;
Для измерения близости друг к другу двух кластеров вводятся следующие метрики:&lt;br /&gt;
&lt;br /&gt;
пусть даны центроиды двух кластеров &amp;lt;math&amp;gt;\vec{X_{01}}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\vec{X_{02}}&amp;lt;/math&amp;gt;.&lt;br /&gt;
Евклидова метрика &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt; и метрика Манхэттена &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt; между двумя кластерами определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_0 = ((\vec{X_{01}}-\vec{X_{02}})^2)^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_1 = |\vec{X_{01}}-\vec{X_{02}}| = \sum_{i=1}^d |{\vec{X_{01}}}^{(i)}-{\vec{X_{02}}}^{(i)}| &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть имеются два кластера, содержащих соответственно  &amp;lt;math&amp;gt;N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;N_2&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i= 1,2, ...,N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\{\vec{X_j}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j= N_1+1,N_1+2, ...,N_1+N_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Среднее расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &#039;&#039;&#039;среднее внутрикластерное расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &#039;&#039;&#039;дисперсия&#039;&#039;&#039; &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; для двух кластеров определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{\sum_{i=1}^{N_1}\sum_{j=N_1+1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{N_1N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{\sum_{i=1}^{N_1+N_2}\sum_{j=1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_4 = \sum_{k=1}^{N_1+N_2}(\vec{X_k} - \frac{\sum_{i=1}^{N_1+N_2}\vec{X_i}}{N_1+N_2})^2 - \sum_{i=1}^{N_1}(\vec{X_i} - \frac{\sum_{i=1}^{N_1}\vec{X_i}}{N_1})^2 - \sum_{j=N_1+1}^{N_1+N_2}(\vec{X_j} - \frac{\sum_{i=N_1+1}^{N_1+N_2}\vec{X_i}}{N_2})^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Таким образом, величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; относятся к отдельным кластерам, а &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; - к объединению двух кластеров.&lt;br /&gt;
&lt;br /&gt;
=== Кластерный элемент и кластерное дерево ===&lt;br /&gt;
&lt;br /&gt;
В основе концепции алгоритма BIRCH лежат понятия &#039;&#039;&#039;кластерного элемента&#039;&#039;&#039; и &#039;&#039;&#039;кластерного дерева (CF Tree)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====Кластерный элемент ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; Пусть в кластере содержатся  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности  &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;:&amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;i=1,2,...,N&amp;lt;/math&amp;gt;. &lt;br /&gt;
&#039;&#039;&#039;Кластерный элемент (CF)&#039;&#039;&#039; - тройка чисел, характеризующая информацию о кластере: &lt;br /&gt;
&amp;lt;math&amp;gt;CF = (N, \vec{LS}, SS)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - количество элементов входных данных, содержащихся в кластере, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; - линейная сумма входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}\vec{X_i}&amp;lt;/math&amp;gt;), &amp;lt;math&amp;gt;SS&amp;lt;/math&amp;gt; - сумма квадратов входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}{\vec{X_i}}^2&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Теорема&#039;&#039;&#039; Пусть &amp;lt;math&amp;gt;CF_1 = (N_1, \vec{LS_1}, SS_1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;CF_2 = (N_1, \vec{LS_2}, SS_2)&amp;lt;/math&amp;gt; - CF векторы двух непересекающихся кластеров. Тогда при их объединении образуется кластер со следующим CF вектором: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF = CF_1 + CF_2 = (N_1+N_2, \vec{LS_1}+\vec{LS_2}, SS_1+SS_2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Из указанных выше определения и теоремы вытекает тот факт, что при объединении кластеров их CF вектор может вычисляться инкрементно и точно. &lt;br /&gt;
Легко показать, что вычислить величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;, как и обычные метрики, также не составит труда.&lt;br /&gt;
&lt;br /&gt;
Таким образом, в данном случае информацией о кластере является не весь набор точек, а вектор CF. Хранение одного только вектора может показаться неэффективным, но этого вполне достаточно для оперирования всеми необходимыми метриками, на основе которых принимаются решения в алгоритме BIRCH.&lt;br /&gt;
&lt;br /&gt;
==== Кластерное дерево ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; &#039;&#039;&#039;Кластерное дерево (CF Tree)&#039;&#039;&#039; - это взвешенно сбалансированное дерево с двумя параметрами: &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - коэффициент разветвления, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - пороговая величина.&lt;br /&gt;
&lt;br /&gt;
Каждый нелистьевой узел дерева имеет не более чем &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; вхождений узлов следующей формы: &amp;lt;math&amp;gt;[CF_i,child_i]&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i=1,2,...,B&amp;lt;/math&amp;gt;, &#039;&#039;child&#039;&#039; - указатель на i-й дочерний узел, &amp;lt;math&amp;gt;CF_i&amp;lt;/math&amp;gt; - CF вектор соответствующего подкластера.&lt;br /&gt;
&lt;br /&gt;
Каждый листьевой узел имеет ссылку на два соседних узла (&#039;&#039;prev&#039;&#039; и &#039;&#039;next&#039;&#039;) для того, чтобы связать все узлы для эффективного сканирования.&lt;br /&gt;
Все листьевые узлы должны удовлетворять пороговому ограничению &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, т.е. диаметр (радиус) не должен превосходить &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;.&lt;br /&gt;
В процессе вставки новых данных CF дерево строится динамически. Оно использует вставку данных для кластеризации точно также как &amp;lt;math&amp;gt;B+&amp;lt;/math&amp;gt; [https://ru.wikipedia.org/wiki/B%2B-%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE дерево] использует её для поиска.&lt;br /&gt;
CF дерево очень компактно, поскольку каждый листьевой узел - это не просто точка, а подкластер (который объединяет множество точек с учётом ограничения &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Операция вставки в &#039;&#039;&#039;CF&#039;&#039;&#039; дерево ====&lt;br /&gt;
&lt;br /&gt;
Опишем алгоритм вставки элемнта &amp;lt;math&amp;gt;Ent&amp;lt;/math&amp;gt; в CF дерево:&lt;br /&gt;
&lt;br /&gt;
1) &#039;&#039;Определение подходящего листа&#039;&#039;: Начиная с корня, алгоритм рекурсивно спускается по CF дереву, выбирая &#039;&#039;&#039;ближайший&#039;&#039;&#039; дочерний узел в соответствии с выбранной метрикой &amp;lt;math&amp;gt;D0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D4&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &#039;&#039;Преобразование листа&#039;&#039;: Когда алгоритм доходит до листа, он находит ближайшую листьевой элемент, скажем, &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;, а затем проверяет, можно ли добавить &#039;&#039;Ent&#039;&#039; к &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt; без нарушения порогового условия. Если да, то с учётом этого изменяется CF вектор для &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;; если нет, то &#039;&#039;Ent&#039;&#039; становится новым элементом листа. Если в листе для этого достаточно места, то шаг окончен, иначе он должен &amp;quot;расщепиться&amp;quot;. Расщепление узла производится при помощи выбора за основу наиболее удалённой друг от друга пары элементов и перераспределение оставшихся элементов в соответствии с выбранным критерием близости.&lt;br /&gt;
&lt;br /&gt;
3) &#039;&#039;Преобразование пути к листу&#039;&#039;: После вставки &#039;&#039;Ent&#039;&#039; в лист мы должны обновить информацию о CF для каждого нелистьевого элемента на пути к листу. При отсутствии расщепления это означает простое сложение CF векторов для отражения факта добавления &#039;&#039;Ent&#039;&#039;. Расщепление листа же требует вставки нового нелистьевого элемента в родительский узел для задания только что созданного листа. Если у родителя есть место для этого элемента, то необходимо просто преобразовать CF векторы на всех более высоких уровнях. В общем случае, однако, нам также придётся расщепить родительский узел, и так далее до корня. Если расщеплён корень, то высота дерева увеличивается на единицу.&lt;br /&gt;
&lt;br /&gt;
4) &#039;&#039;Улучшение слияния&#039;&#039;: Расщепление вызвано ограничением на размер узла, который не зависит от кластеризационных свойств данных. Если во входящем потоке присутствуют &amp;quot;искажённые&amp;quot; (из областей с низкой плотностью) данные, это может повлиять на качество кластеризации, а также уменьшить эффективность использования памяти. Дополнительный шаг алгоритма помогает решить эти проблемы: предположим, что произошло расщепление листа, и распространение этого процесса остановилось на некотором нелистьевом узле &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt;, то есть &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; может вместить дополнительный элемент, полученный после расщепления. Теперь мы сканируем узел &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; для нахождения двух наиболее близких элементов. Если это не пара, отвечающая расщеплению, мы пытаемся объединить их и поставить в соответствие два дочерних узла. Если количество элементов в дочерних узлах  больше B, мы снова расщепляем результат объединения.&lt;br /&gt;
В процессе повторного расщепления, в случае, если один источник собирает достаточно элементов для того, чтобы полностью заполнить узел, оставшиеся элементы передаются другом источнику. В итоге, если объединённые элементы помещаются в одном узле, в нём освобождается место для ещё одного элемента. Тем самым увеличивается степень использования свободного пространства и откладывается дальнейшее расщепление. В ином случае мы улучшаем распределение элементов в двух ближайших подкластерах.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро алгоритма заключается в многократном выполнении операции вставки нового элемента в дерево, в процессе чего требуется вычисление следующих величин:&lt;br /&gt;
&lt;br /&gt;
* радиуса &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; или диаметра &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластерного элемента. Выполняется при попытке вставить новый элемент в один из подкластеров листьевого узла дерева.&lt;br /&gt;
&lt;br /&gt;
* расстояния между двумя элементами. Выполняется при поиске ближайшего по отношению к новому элементу подкластера в узле дерева по одной из рассмотренных в разд. 1.2.1 метрик &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Зная характеристики кластерных элементов &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;, в результате алгебраических преобразований можно получить следующие упрощенные формулы вычисления необходимых значений:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\vec{X_0} = \frac{\vec{LS}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{SS - 2\vec{X_0}\vec{LS} + N(\vec{X_0})^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{2(N*SS - (\vec{LS})^2)}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{N_1*SS_2 + N_2*SS_1 - 2\vec{LS_1}\vec{LS_2}}{N_1*N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{2((N_1+N_2)(SS_1+SS_2)-(\vec{LS_1}+\vec{LS_2})^2)}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Реализация алгоритма BIRCH состояит из следующих четырёх фаз:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 1&#039;&#039;&#039;. Главной задачей фазы 1 является сканирование всех данных и построение в памяти исходного CF дерева, используя заданное количество памяти. Это дерево стремится отразить информацию о кластеризации данных настолько хорошо, насколько это позволяют ограничения по памяти. При этом плотно распределённые данные группируются в подкластеры, а более разрозненные данные удаляются. После завершения фазы 1 вспомогательные вычисления в дальнейших фазах будут:&lt;br /&gt;
&lt;br /&gt;
1) быстрее, потому что (а) больше не нужны операции ввода-вывода, (b) проблема кластеризации начальных данных упрощается до проблемы кластеризации подкластеров в листьях;&lt;br /&gt;
&lt;br /&gt;
2) точнее, потому что (а) большинство данных с низкой плотностью удалены, (b) оставшиеся данные распределены оптимально (в соответствии с доступным количеством памяти);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 2&#039;&#039;&#039;. Данная фаза является опциональной. Известно, что существующие методы глобальной кластеризации, используемые в рамках фазы 3, имеют различные диапазоны входных значений, при которых их реализация наиболее эффективна. Поэтому потенциально существует пробел между размером фазы 1 и входными значениями фазы 3. И фаза 2 как раз является недостающим связующим звеном: так же как и фаза 1, она сканирует листьевые элементы начального CF дерева для того, чтобы построить меньшее дерево, удаляя ещё больше элементов с низкой плотностью и группируя переполненные подкластеры в большие кластеры.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 3&#039;&#039;&#039;. В данной фазе для листьевых элементов применяется (любой подходящий) алгоритм глобальной кластеризации. Существующие алгоритмы кластеризации наборов точек могут также работать с наборами подкластеров, каждый из которых представлен своим CF вектором. Зная CF вектор, можно вычислить центроид и в дальнейшем заменить всю информацию о кластере этим значением (этого достаточно для вычисления большинства необходимых метрик). После фазы 3 мы получаем набор кластеров, который отражает основные характеристики распределяемых данных.&lt;br /&gt;
Однако, всё ещё могут оставаться некоторые неточности, для устранения которых существует фаза 4.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 4&#039;&#039;&#039;. Данная фаза является опциональной и влечёт за собой затраты на дополнительное сканирование данных для корректировки неточностей и дальнейшего улучшения кластеризации. Фаза 4 использует центроиды кластеров, полученные в фазе 3 для как основы и перераспределяет точки входных данных в ближайшие для них основы для получения нового списка кластеров. Фаза 4, если это необходимо пользователю, может быть расширена дополнительными проходами для уверенности в том, что результат приближается к оптимальному.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Последовательную реализацию основных операций алгоритма BIRCH можно продемонстрировать на примере следующего фрагмента кода на языке C++:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot;&amp;gt;&lt;br /&gt;
void CF_Node::insert(const CF_Cluster &amp;amp;entry)&lt;br /&gt;
{&lt;br /&gt;
    //Находим ближайший к новому элементу подкластер в узле&lt;br /&gt;
    СF_Vector_it closest = entry.findClosest(subclusters);&lt;br /&gt;
    //Если узел пустой, добавляем в него новый подкластер&lt;br /&gt;
    if (closest == subclusters.end()) {&lt;br /&gt;
        subclusters.push_back(entry);&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    closest-&amp;gt;add(entry);&lt;br /&gt;
    //Если узел является листьевым, и ближайший подкластер не может вместить&lt;br /&gt;
    //новый элемент, добавляем в узел новый подкластер&lt;br /&gt;
    if (leaf) {&lt;br /&gt;
        if (closest-&amp;gt;D &amp;gt; threshold) {&lt;br /&gt;
            closest-&amp;gt;remove(entry);&lt;br /&gt;
            subclusters.push_back(entry);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else {&lt;br /&gt;
        CF_Node *node = closest-&amp;gt;child;&lt;br /&gt;
        node-&amp;gt;insert(entry);&lt;br /&gt;
        //Если при добавлении нового элемента в дочерний узел тот переполнился,&lt;br /&gt;
        //расщепляем его        &lt;br /&gt;
        if (node-&amp;gt;getSubclusters().size() &amp;gt; bFactor) {&lt;br /&gt;
            CF_Vector newClusters = node-&amp;gt;splitNode();&lt;br /&gt;
            delete node;&lt;br /&gt;
            subclusters.erase(closest);&lt;br /&gt;
            subclusters.insert(subclusters.end(), newClusters.begin(), newClusters.end());&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    //Если узел является корневым и он переполнен, расщепляем его&lt;br /&gt;
    if (root &amp;amp;&amp;amp; subclusters.size() &amp;gt; bFactor) {&lt;br /&gt;
        subclusters = splitNode();&lt;br /&gt;
        leaf = false;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
CF_Vector CF_Node::splitNode()&lt;br /&gt;
{&lt;br /&gt;
    if (subclusters.size() &amp;lt; 2)&lt;br /&gt;
        return (root) ? subclusters : CF_Vector{CF_Cluster(this)};&lt;br /&gt;
    //Находим пару наиболее удаленных друг от друга подкластеров&lt;br /&gt;
    CF_Vector_it pole1, pole2;&lt;br /&gt;
    data_t longestDist = 0.0;&lt;br /&gt;
    for (auto lhs = subclusters.begin(); lhs != subclusters.end() - 1; ++lhs) {&lt;br /&gt;
        for (auto rhs = lhs + 1; rhs != subclusters.end(); ++rhs) {&lt;br /&gt;
            auto distance = getDistance(*lhs, *rhs);&lt;br /&gt;
            if (distance &amp;gt; longestDist) {&lt;br /&gt;
                longestDist = distance;&lt;br /&gt;
                pole1 = lhs;&lt;br /&gt;
                pole2 = rhs;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    //Разделяем множество всех подкластеров узла на две части&lt;br /&gt;
    CF_Vector subclusters1, subclusters2;&lt;br /&gt;
    for (auto it = subclusters.begin(); it != subclusters.end(); ++it) {&lt;br /&gt;
        if (getDistance(*it, *pole1) &amp;lt; getDistance(*it, *pole2))&lt;br /&gt;
            subclusters1.push_back(*it);&lt;br /&gt;
        else&lt;br /&gt;
            subclusters2.push_back(*it);&lt;br /&gt;
    }&lt;br /&gt;
    //Создаем два новых узла&lt;br /&gt;
    CF_Node *node1 = new CF_Node(threshold, bFactor, count, leaf, subclusters1),&lt;br /&gt;
            *node2 = new CF_Node(threshold, bFactor, count, leaf, subclusters2);&lt;br /&gt;
    //Связываем листья&lt;br /&gt;
    if (leaf) {&lt;br /&gt;
        if (prevLeaf) {&lt;br /&gt;
            node1-&amp;gt;setPrevLeaf(prevLeaf);&lt;br /&gt;
            prevLeaf-&amp;gt;setNextLeaf(node1);&lt;br /&gt;
        }&lt;br /&gt;
        if (nextLeaf) {&lt;br /&gt;
            node2-&amp;gt;setNextLeaf(nextLeaf);&lt;br /&gt;
            nextLeaf-&amp;gt;setPrevLeaf(node2);&lt;br /&gt;
        }&lt;br /&gt;
        node1-&amp;gt;setNextLeaf(node2);&lt;br /&gt;
        node2-&amp;gt;setPrevLeaf(node1);&lt;br /&gt;
    }&lt;br /&gt;
    CF_Cluster cluster1(node1), cluster2(node2);&lt;br /&gt;
    return CF_Vector{cluster1, cluster2};&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Для начала проанализируем вычислительную сложность фазы 1.&lt;br /&gt;
Максимальный размер дерева &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt; - ограничение по памяти на размер узла, а &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - общий объем памяти. Для того чтобы вставить элемент, мы должны пройти путь от корня до листа (это около &amp;lt;math&amp;gt;1+log_B\frac{M}{P}&amp;lt;/math&amp;gt; узлов). В каждом узле в поисках &amp;quot;ближайшего&amp;quot; нам необходимо просмотреть B элементов; сложность для каждого элемента пропорциональна размерности &#039;&#039;d&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Поэтому сложность вставки всех входных точек &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В случае, когда необходимо перестроить дерево, предположим, что ES - это размер CF элемента. Существует максимум &amp;lt;math&amp;gt;\frac{M}{ES}&amp;lt;/math&amp;gt; листьевых элементов для вставки, поэтому сложность повторной вставки листьевых элементов &amp;lt;math&amp;gt;O(d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Количество итераций перестройки дерева зависит от пороговой величины. На самом деле, это около &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; (двоичное основание появилось из-за того, что мы не можем провести оценку более чем в 2 раза отличающуюся от текущего размера). &amp;lt;math&amp;gt;N_0&amp;lt;/math&amp;gt; - это число входных точек, загруженных в память с пороговым ограничением &amp;lt;math&amp;gt;T_0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Соответственно, итоговая сложность фазы 1 &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P})+log_2\frac{N}{N_0}*d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Анализ фазы 2 проводится аналогично.&lt;br /&gt;
&lt;br /&gt;
Что касается операций ввода-вывода, то в фазе 1 данные сканируются один раз, а в фазе 2 не сканируются вовсе.&lt;br /&gt;
Некоторое количество вычислений связано с удалением точек из областей с низкой плотностью.&lt;br /&gt;
Если количество доступной для этой операции памяти не больше &#039;&#039;M&#039;&#039; и проведено порядка &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; перестроек дерева, то сложность ввода-вывода для фазы 1 существенно не отличается от сложности чтения из файла. Основываясь рассуждениях выше, сложность фаз 1 и 2 будет линейно увеличиваться с ростом N.&lt;br /&gt;
&lt;br /&gt;
В фазе 3 нет операций ввода-вывода. Её сложность ограничена константой, которая зависит от максимального размера входных данных, и варианта выбранного алгоритма для кластеризации. &lt;br /&gt;
&lt;br /&gt;
Фаза 4 снова сканирует данные и записывает каждую точку в подходящий кластер; время работы пропорционально &amp;lt;math&amp;gt;N*K&amp;lt;/math&amp;gt;.   &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
=== Вычисление расстояния ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2=\frac{N_1*SS_2+N_2*SS_1-2*\vec{LS_1}*\vec{LS_2}}{N_1*N_2}&amp;lt;/math&amp;gt;, где&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF_1=[N_1,\vec{LS_1},SS_1]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF_2=[N_2,\vec{LS_2},SS_2]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:ZgYL51QJsQk.jpg|500px|thumb|center]]&lt;br /&gt;
&amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельно могут быть выполнены следующие шаги алгоритма:&lt;br /&gt;
* Нахождение ближайшего к новому элементу подкластера в узле при выполнении операции вставки. Это возможно за счет того, что расстояние между парами элементов может быть вычислено независимо друг от друга. Сложность &lt;br /&gt;
* Вычисление величин &amp;lt;math&amp;gt;\vec{LS},\vec{X0}, R, D, D_0-D_4&amp;lt;/math&amp;gt;, в процессе чего выполняются операции сложения и скалярного произведения векторов.&lt;br /&gt;
&lt;br /&gt;
Другим способом параллелизации алгоритма может служить создание и заполнение сразу множества кластерных деревьев, между которыми будут распределены входные данные. Множество всех подкластеров листьевых узлов полученных таким образом деревьев может быть подвергнуто глобальной кластеризации с помощью какого-либо из известных параллельных алгоритмов, например, k-средних&amp;lt;ref&amp;gt;[http://people.du.ac.in/~ngupta/Publications/PBIRCH%20A%20Sacalabel%20Paralllel%20Clustering.pdf A Garg, N Gupta PBIRCH: A Scalable Parallel Clustering algorithm for Incremental Data]&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;
* Набор из &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек &amp;lt;math&amp;gt;\{X_i\}, i=1,...,N&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Кластерное дерево с не более чем &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt; узлами.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Достоинства алгоритма ===&lt;br /&gt;
По сравнению с предыдущими методами BIRCH обладает следующими достоинствами:&lt;br /&gt;
&lt;br /&gt;
1. BIRCH является локальным алгоритмом, то есть каждое решение о каждом элементе кластера принимается без повторного сканирования данных или уже существующих кластеров. Используются только метрики, отражающие близость элементов друг к другу.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH использует факт неравномерного распределения данных в пространстве и поэтому не все данные рассматриваются как одинаково важные для построения кластера. Области с большой плотностью обрабатываются как единый кластер. Данные в более разреженных областях могут удаляться (опционально).&lt;br /&gt;
&lt;br /&gt;
3. BIRCH использует всю доступную память для получения наилучших из возможных подкластеров, в то же время минимизируя затраты на операции ввода/вывода. Оптимизация процесса кластеризации достигается за счет использования взвешенно-сбалансированного дерева. При этом время исполнения линейно.&lt;br /&gt;
&lt;br /&gt;
4. BIRCH не требует всего набора данных заранее (при этом просматривает его всего один раз).&lt;br /&gt;
&lt;br /&gt;
=== Недостатки алгоритма ===&lt;br /&gt;
&lt;br /&gt;
1. Алгоритм позволяет работать только с числовыми данными.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH хорошо выделяет только кластеры сферической формы.&lt;br /&gt;
&lt;br /&gt;
3. Существует необходимость в задании пороговых значений.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
В составе пакетов и библиотек:&lt;br /&gt;
* [http://scikit-learn.org/stable/modules/generated/sklearn.cluster.Birch.html scikit-learn]&lt;br /&gt;
* [http://cucis.ece.northwestern.edu/projects/DMS/MineBench.html NU-MineBench]&lt;br /&gt;
Пользовательские реализации:&lt;br /&gt;
* [https://code.google.com/archive/p/jbirch/ JBIRCH]&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Светлана Морозова</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13836</id>
		<title>Участник:Smirnov.maxim/BIRCH</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13836"/>
		<updated>2016-10-26T07:26:56Z</updated>

		<summary type="html">&lt;p&gt;Светлана Морозова: /* Вычисление расстояния */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Авторы: [[Участник:Светлана Морозова|Морозова Светлана]], [[Участник:Smirnov.maxim|Смирнов Максим]].&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Нахождение полезных для анализа закономерностей в больших объёмах данных с недавних пор вызывает значительный интерес. В связи с этим ввелось и стало активно развиваться такое понятие как &#039;&#039;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7 кластеризация]&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Ранние работы и алгоритмы, разработанные в этой области, не уделяли достаточного внимания анализу очень больших наборов данных или минимизации издержек на процессы ввода-вывода.&lt;br /&gt;
Решением этих проблем стал алгоритм, известный как BIRCH.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIRCH&#039;&#039;&#039;&amp;lt;ref&amp;gt;[http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf Нейский И.М. Классификация и сравнение методов кластеризации]&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;[http://www.cs.sfu.ca/CourseCentral/459/han/papers/zhang96.pdf T Zhang, R Ramakrishnan, M Livny. BIRCH: An Efficient Data Clustering Method for Very Large Databases]&amp;lt;/ref&amp;gt; (balanced iterative reducing and clustering using hierarchies)- алгоритм, применяемый в области [https://ru.wikipedia.org/wiki/Data_mining Data mining] и использующий принципы [https://ru.wikipedia.org/wiki/%D0%98%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F иерархической кластеризации].&lt;br /&gt;
&lt;br /&gt;
Если имеется очень большой набор данных, то в пространстве он распределен, как правило, неравномерно. Кластерный анализ определяет места наибольшего и наименьшего скоплений, чтобы таким образом понять всю картину целиком. Кроме того, полученные кластеры визуализируются гораздо нагляднее, чем начальные &amp;quot;сырые&amp;quot; данные.&lt;br /&gt;
Задачей алгоритмов кластеризации является не только простое разбиение данных на кластеры, но и работа в рамках ограниченного объёма доступной памяти (как правило, её объём гораздо меньше, чем размер исходного набора данных) и минимизация времени, требуемого на операции ввода-вывода.&lt;br /&gt;
&lt;br /&gt;
Для наилучшего решения этих проблем BIRCH распределяет входящие данные по кластерам динамически. Для эффективной кластеризации алгоритму требуется всего одно сканирование данных (т.е. с увеличением количества данных сложность увеличивается линейно). А при помощи одной (или более) дополнительных итераций можно и далее улучшать эффективность. BIRCH также является первым алгоритмом, предложенным для эффективного управления &amp;quot;шумами&amp;quot; (данными, которые не вписываются в общее представление модели).&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Теоретическая основа ===&lt;br /&gt;
&lt;br /&gt;
Пусть в кластере имеются &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}, i=1,2,...,N&amp;lt;/math&amp;gt;.&lt;br /&gt;
Тогда &#039;&#039;&#039;центроид&#039;&#039;&#039; &amp;lt;math&amp;gt;{\vec{{X_0}}}&amp;lt;/math&amp;gt;, &#039;&#039;&#039;радиус&#039;&#039;&#039; &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &#039;&#039;&#039;диаметр&#039;&#039;&#039; &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластера определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;{\vec{X_0}}=\frac{\sum_{i=1}^N\vec{X_i}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{\sum_{i=1}^N{(\vec{X_i} - \vec{X_0})}^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{\sum_{i=1}^N\sum_{j=1}^N{(\vec{X_i} - \vec{X_j})}^2}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; - это среднее расстояние от каждой точки до центроида. &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; - это среднее расстояние между парами в кластере. Данные величины являются альтернативными метриками плотности кластера относительно центроида.&lt;br /&gt;
&lt;br /&gt;
Для измерения близости друг к другу двух кластеров вводятся следующие метрики:&lt;br /&gt;
&lt;br /&gt;
пусть даны центроиды двух кластеров &amp;lt;math&amp;gt;\vec{X_{01}}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\vec{X_{02}}&amp;lt;/math&amp;gt;.&lt;br /&gt;
Евклидова метрика &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt; и метрика Манхэттена &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt; между двумя кластерами определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_0 = ((\vec{X_{01}}-\vec{X_{02}})^2)^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_1 = |\vec{X_{01}}-\vec{X_{02}}| = \sum_{i=1}^d |{\vec{X_{01}}}^{(i)}-{\vec{X_{02}}}^{(i)}| &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть имеются два кластера, содержащих соответственно  &amp;lt;math&amp;gt;N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;N_2&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i= 1,2, ...,N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\{\vec{X_j}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j= N_1+1,N_1+2, ...,N_1+N_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Среднее расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &#039;&#039;&#039;среднее внутрикластерное расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &#039;&#039;&#039;дисперсия&#039;&#039;&#039; &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; для двух кластеров определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{\sum_{i=1}^{N_1}\sum_{j=N_1+1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{N_1N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{\sum_{i=1}^{N_1+N_2}\sum_{j=1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_4 = \sum_{k=1}^{N_1+N_2}(\vec{X_k} - \frac{\sum_{i=1}^{N_1+N_2}\vec{X_i}}{N_1+N_2})^2 - \sum_{i=1}^{N_1}(\vec{X_i} - \frac{\sum_{i=1}^{N_1}\vec{X_i}}{N_1})^2 - \sum_{j=N_1+1}^{N_1+N_2}(\vec{X_j} - \frac{\sum_{i=N_1+1}^{N_1+N_2}\vec{X_i}}{N_2})^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Таким образом, величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; относятся к отдельным кластерам, а &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; - к объединению двух кластеров.&lt;br /&gt;
&lt;br /&gt;
=== Кластерный элемент и кластерное дерево ===&lt;br /&gt;
&lt;br /&gt;
В основе концепции алгоритма BIRCH лежат понятия &#039;&#039;&#039;кластерного элемента&#039;&#039;&#039; и &#039;&#039;&#039;кластерного дерева (CF Tree)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====Кластерный элемент ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; Пусть в кластере содержатся  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности  &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;:&amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;i=1,2,...,N&amp;lt;/math&amp;gt;. &lt;br /&gt;
&#039;&#039;&#039;Кластерный элемент (CF)&#039;&#039;&#039; - тройка чисел, характеризующая информацию о кластере: &lt;br /&gt;
&amp;lt;math&amp;gt;CF = (N, \vec{LS}, SS)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - количество элементов входных данных, содержащихся в кластере, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; - линейная сумма входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}\vec{X_i}&amp;lt;/math&amp;gt;), &amp;lt;math&amp;gt;SS&amp;lt;/math&amp;gt; - сумма квадратов входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}{\vec{X_i}}^2&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Теорема&#039;&#039;&#039; Пусть &amp;lt;math&amp;gt;CF_1 = (N_1, \vec{LS_1}, SS_1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;CF_2 = (N_1, \vec{LS_2}, SS_2)&amp;lt;/math&amp;gt; - CF векторы двух непересекающихся кластеров. Тогда при их объединении образуется кластер со следующим CF вектором: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF = CF_1 + CF_2 = (N_1+N_2, \vec{LS_1}+\vec{LS_2}, SS_1+SS_2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Из указанных выше определения и теоремы вытекает тот факт, что при объединении кластеров их CF вектор может вычисляться инкрементно и точно. &lt;br /&gt;
Легко показать, что вычислить величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;, как и обычные метрики, также не составит труда.&lt;br /&gt;
&lt;br /&gt;
Таким образом, в данном случае информацией о кластере является не весь набор точек, а вектор CF. Хранение одного только вектора может показаться неэффективным, но этого вполне достаточно для оперирования всеми необходимыми метриками, на основе которых принимаются решения в алгоритме BIRCH.&lt;br /&gt;
&lt;br /&gt;
==== Кластерное дерево ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; &#039;&#039;&#039;Кластерное дерево (CF Tree)&#039;&#039;&#039; - это взвешенно сбалансированное дерево с двумя параметрами: &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - коэффициент разветвления, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - пороговая величина.&lt;br /&gt;
&lt;br /&gt;
Каждый нелистьевой узел дерева имеет не более чем &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; вхождений узлов следующей формы: &amp;lt;math&amp;gt;[CF_i,child_i]&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i=1,2,...,B&amp;lt;/math&amp;gt;, &#039;&#039;child&#039;&#039; - указатель на i-й дочерний узел, &amp;lt;math&amp;gt;CF_i&amp;lt;/math&amp;gt; - CF вектор соответствующего подкластера.&lt;br /&gt;
&lt;br /&gt;
Каждый листьевой узел имеет ссылку на два соседних узла (&#039;&#039;prev&#039;&#039; и &#039;&#039;next&#039;&#039;) для того, чтобы связать все узлы для эффективного сканирования.&lt;br /&gt;
Все листьевые узлы должны удовлетворять пороговому ограничению &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, т.е. диаметр (радиус) не должен превосходить &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;.&lt;br /&gt;
В процессе вставки новых данных CF дерево строится динамически. Оно использует вставку данных для кластеризации точно также как &amp;lt;math&amp;gt;B+&amp;lt;/math&amp;gt; [https://ru.wikipedia.org/wiki/B%2B-%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE дерево] использует её для поиска.&lt;br /&gt;
CF дерево очень компактно, поскольку каждый листьевой узел - это не просто точка, а подкластер (который объединяет множество точек с учётом ограничения &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Операция вставки в &#039;&#039;&#039;CF&#039;&#039;&#039; дерево ====&lt;br /&gt;
&lt;br /&gt;
Опишем алгоритм вставки элемнта &amp;lt;math&amp;gt;Ent&amp;lt;/math&amp;gt; в CF дерево:&lt;br /&gt;
&lt;br /&gt;
1) &#039;&#039;Определение подходящего листа&#039;&#039;: Начиная с корня, алгоритм рекурсивно спускается по CF дереву, выбирая &#039;&#039;&#039;ближайший&#039;&#039;&#039; дочерний узел в соответствии с выбранной метрикой &amp;lt;math&amp;gt;D0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D4&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &#039;&#039;Преобразование листа&#039;&#039;: Когда алгоритм доходит до листа, он находит ближайшую листьевой элемент, скажем, &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;, а затем проверяет, можно ли добавить &#039;&#039;Ent&#039;&#039; к &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt; без нарушения порогового условия. Если да, то с учётом этого изменяется CF вектор для &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;; если нет, то &#039;&#039;Ent&#039;&#039; становится новым элементом листа. Если в листе для этого достаточно места, то шаг окончен, иначе он должен &amp;quot;расщепиться&amp;quot;. Расщепление узла производится при помощи выбора за основу наиболее удалённой друг от друга пары элементов и перераспределение оставшихся элементов в соответствии с выбранным критерием близости.&lt;br /&gt;
&lt;br /&gt;
3) &#039;&#039;Преобразование пути к листу&#039;&#039;: После вставки &#039;&#039;Ent&#039;&#039; в лист мы должны обновить информацию о CF для каждого нелистьевого элемента на пути к листу. При отсутствии расщепления это означает простое сложение CF векторов для отражения факта добавления &#039;&#039;Ent&#039;&#039;. Расщепление листа же требует вставки нового нелистьевого элемента в родительский узел для задания только что созданного листа. Если у родителя есть место для этого элемента, то необходимо просто преобразовать CF векторы на всех более высоких уровнях. В общем случае, однако, нам также придётся расщепить родительский узел, и так далее до корня. Если расщеплён корень, то высота дерева увеличивается на единицу.&lt;br /&gt;
&lt;br /&gt;
4) &#039;&#039;Улучшение слияния&#039;&#039;: Расщепление вызвано ограничением на размер узла, который не зависит от кластеризационных свойств данных. Если во входящем потоке присутствуют &amp;quot;искажённые&amp;quot; (из областей с низкой плотностью) данные, это может повлиять на качество кластеризации, а также уменьшить эффективность использования памяти. Дополнительный шаг алгоритма помогает решить эти проблемы: предположим, что произошло расщепление листа, и распространение этого процесса остановилось на некотором нелистьевом узле &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt;, то есть &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; может вместить дополнительный элемент, полученный после расщепления. Теперь мы сканируем узел &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; для нахождения двух наиболее близких элементов. Если это не пара, отвечающая расщеплению, мы пытаемся объединить их и поставить в соответствие два дочерних узла. Если количество элементов в дочерних узлах  больше B, мы снова расщепляем результат объединения.&lt;br /&gt;
В процессе повторного расщепления, в случае, если один источник собирает достаточно элементов для того, чтобы полностью заполнить узел, оставшиеся элементы передаются другом источнику. В итоге, если объединённые элементы помещаются в одном узле, в нём освобождается место для ещё одного элемента. Тем самым увеличивается степень использования свободного пространства и откладывается дальнейшее расщепление. В ином случае мы улучшаем распределение элементов в двух ближайших подкластерах.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро алгоритма заключается в многократном выполнении операции вставки нового элемента в дерево, в процессе чего требуется вычисление следующих величин:&lt;br /&gt;
&lt;br /&gt;
* радиуса &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; или диаметра &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластерного элемента. Выполняется при попытке вставить новый элемент в один из подкластеров листьевого узла дерева.&lt;br /&gt;
&lt;br /&gt;
* расстояния между двумя элементами. Выполняется при поиске ближайшего по отношению к новому элементу подкластера в узле дерева по одной из рассмотренных в разд. 1.2.1 метрик &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Зная характеристики кластерных элементов &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;, в результате алгебраических преобразований можно получить следующие упрощенные формулы вычисления необходимых значений:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\vec{X_0} = \frac{\vec{LS}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{SS - 2\vec{X_0}\vec{LS} + N(\vec{X_0})^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{2(N*SS - (\vec{LS})^2)}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{N_1*SS_2 + N_2*SS_1 - 2\vec{LS_1}\vec{LS_2}}{N_1*N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{2((N_1+N_2)(SS_1+SS_2)-(\vec{LS_1}+\vec{LS_2})^2)}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Реализация алгоритма BIRCH состояит из следующих четырёх фаз:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 1&#039;&#039;&#039;. Главной задачей фазы 1 является сканирование всех данных и построение в памяти исходного CF дерева, используя заданное количество памяти. Это дерево стремится отразить информацию о кластеризации данных настолько хорошо, насколько это позволяют ограничения по памяти. При этом плотно распределённые данные группируются в подкластеры, а более разрозненные данные удаляются. После завершения фазы 1 вспомогательные вычисления в дальнейших фазах будут:&lt;br /&gt;
&lt;br /&gt;
1) быстрее, потому что (а) больше не нужны операции ввода-вывода, (b) проблема кластеризации начальных данных упрощается до проблемы кластеризации подкластеров в листьях;&lt;br /&gt;
&lt;br /&gt;
2) точнее, потому что (а) большинство данных с низкой плотностью удалены, (b) оставшиеся данные распределены оптимально (в соответствии с доступным количеством памяти);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 2&#039;&#039;&#039;. Данная фаза является опциональной. Известно, что существующие методы глобальной кластеризации, используемые в рамках фазы 3, имеют различные диапазоны входных значений, при которых их реализация наиболее эффективна. Поэтому потенциально существует пробел между размером фазы 1 и входными значениями фазы 3. И фаза 2 как раз является недостающим связующим звеном: так же как и фаза 1, она сканирует листьевые элементы начального CF дерева для того, чтобы построить меньшее дерево, удаляя ещё больше элементов с низкой плотностью и группируя переполненные подкластеры в большие кластеры.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 3&#039;&#039;&#039;. В данной фазе для листьевых элементов применяется (любой подходящий) алгоритм глобальной кластеризации. Существующие алгоритмы кластеризации наборов точек могут также работать с наборами подкластеров, каждый из которых представлен своим CF вектором. Зная CF вектор, можно вычислить центроид и в дальнейшем заменить всю информацию о кластере этим значением (этого достаточно для вычисления большинства необходимых метрик). После фазы 3 мы получаем набор кластеров, который отражает основные характеристики распределяемых данных.&lt;br /&gt;
Однако, всё ещё могут оставаться некоторые неточности, для устранения которых существует фаза 4.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 4&#039;&#039;&#039;. Данная фаза является опциональной и влечёт за собой затраты на дополнительное сканирование данных для корректировки неточностей и дальнейшего улучшения кластеризации. Фаза 4 использует центроиды кластеров, полученные в фазе 3 для как основы и перераспределяет точки входных данных в ближайшие для них основы для получения нового списка кластеров. Фаза 4, если это необходимо пользователю, может быть расширена дополнительными проходами для уверенности в том, что результат приближается к оптимальному.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Последовательную реализацию основных операций алгоритма BIRCH можно продемонстрировать на примере следующего фрагмента кода на языке C++:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot;&amp;gt;&lt;br /&gt;
void CF_Node::insert(const CF_Cluster &amp;amp;entry)&lt;br /&gt;
{&lt;br /&gt;
    //Находим ближайший к новому элементу подкластер в узле&lt;br /&gt;
    СF_Vector_it closest = entry.findClosest(subclusters);&lt;br /&gt;
    //Если узел пустой, добавляем в него новый подкластер&lt;br /&gt;
    if (closest == subclusters.end()) {&lt;br /&gt;
        subclusters.push_back(entry);&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    closest-&amp;gt;add(entry);&lt;br /&gt;
    //Если узел является листьевым, и ближайший подкластер не может вместить&lt;br /&gt;
    //новый элемент, добавляем в узел новый подкластер&lt;br /&gt;
    if (leaf) {&lt;br /&gt;
        if (closest-&amp;gt;D &amp;gt; threshold) {&lt;br /&gt;
            closest-&amp;gt;remove(entry);&lt;br /&gt;
            subclusters.push_back(entry);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else {&lt;br /&gt;
        CF_Node *node = closest-&amp;gt;child;&lt;br /&gt;
        node-&amp;gt;insert(entry);&lt;br /&gt;
        //Если при добавлении нового элемента в дочерний узел тот переполнился,&lt;br /&gt;
        //расщепляем его        &lt;br /&gt;
        if (node-&amp;gt;getSubclusters().size() &amp;gt; bFactor) {&lt;br /&gt;
            CF_Vector newClusters = node-&amp;gt;splitNode();&lt;br /&gt;
            delete node;&lt;br /&gt;
            subclusters.erase(closest);&lt;br /&gt;
            subclusters.insert(subclusters.end(), newClusters.begin(), newClusters.end());&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    //Если узел является корневым и он переполнен, расщепляем его&lt;br /&gt;
    if (root &amp;amp;&amp;amp; subclusters.size() &amp;gt; bFactor) {&lt;br /&gt;
        subclusters = splitNode();&lt;br /&gt;
        leaf = false;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
CF_Vector CF_Node::splitNode()&lt;br /&gt;
{&lt;br /&gt;
    if (subclusters.size() &amp;lt; 2)&lt;br /&gt;
        return (root) ? subclusters : CF_Vector{CF_Cluster(this)};&lt;br /&gt;
    //Находим пару наиболее удаленных друг от друга подкластеров&lt;br /&gt;
    CF_Vector_it pole1, pole2;&lt;br /&gt;
    data_t longestDist = 0.0;&lt;br /&gt;
    for (auto lhs = subclusters.begin(); lhs != subclusters.end() - 1; ++lhs) {&lt;br /&gt;
        for (auto rhs = lhs + 1; rhs != subclusters.end(); ++rhs) {&lt;br /&gt;
            auto distance = getDistance(*lhs, *rhs);&lt;br /&gt;
            if (distance &amp;gt; longestDist) {&lt;br /&gt;
                longestDist = distance;&lt;br /&gt;
                pole1 = lhs;&lt;br /&gt;
                pole2 = rhs;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    //Разделяем множество всех подкластеров узла на две части&lt;br /&gt;
    CF_Vector subclusters1, subclusters2;&lt;br /&gt;
    for (auto it = subclusters.begin(); it != subclusters.end(); ++it) {&lt;br /&gt;
        if (getDistance(*it, *pole1) &amp;lt; getDistance(*it, *pole2))&lt;br /&gt;
            subclusters1.push_back(*it);&lt;br /&gt;
        else&lt;br /&gt;
            subclusters2.push_back(*it);&lt;br /&gt;
    }&lt;br /&gt;
    //Создаем два новых узла&lt;br /&gt;
    CF_Node *node1 = new CF_Node(threshold, bFactor, count, leaf, subclusters1),&lt;br /&gt;
            *node2 = new CF_Node(threshold, bFactor, count, leaf, subclusters2);&lt;br /&gt;
    //Связываем листья&lt;br /&gt;
    if (leaf) {&lt;br /&gt;
        if (prevLeaf) {&lt;br /&gt;
            node1-&amp;gt;setPrevLeaf(prevLeaf);&lt;br /&gt;
            prevLeaf-&amp;gt;setNextLeaf(node1);&lt;br /&gt;
        }&lt;br /&gt;
        if (nextLeaf) {&lt;br /&gt;
            node2-&amp;gt;setNextLeaf(nextLeaf);&lt;br /&gt;
            nextLeaf-&amp;gt;setPrevLeaf(node2);&lt;br /&gt;
        }&lt;br /&gt;
        node1-&amp;gt;setNextLeaf(node2);&lt;br /&gt;
        node2-&amp;gt;setPrevLeaf(node1);&lt;br /&gt;
    }&lt;br /&gt;
    CF_Cluster cluster1(node1), cluster2(node2);&lt;br /&gt;
    return CF_Vector{cluster1, cluster2};&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Для начала проанализируем вычислительную сложность фазы 1.&lt;br /&gt;
Максимальный размер дерева &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt; - ограничение по памяти на размер узла, а &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - общий объем памяти. Для того чтобы вставить элемент, мы должны пройти путь от корня до листа (это около &amp;lt;math&amp;gt;1+log_B\frac{M}{P}&amp;lt;/math&amp;gt; узлов). В каждом узле в поисках &amp;quot;ближайшего&amp;quot; нам необходимо просмотреть B элементов; сложность для каждого элемента пропорциональна размерности &#039;&#039;d&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Поэтому сложность вставки всех входных точек &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В случае, когда необходимо перестроить дерево, предположим, что ES - это размер CF элемента. Существует максимум &amp;lt;math&amp;gt;\frac{M}{ES}&amp;lt;/math&amp;gt; листьевых элементов для вставки, поэтому сложность повторной вставки листьевых элементов &amp;lt;math&amp;gt;O(d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Количество итераций перестройки дерева зависит от пороговой величины. На самом деле, это около &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; (двоичное основание появилось из-за того, что мы не можем провести оценку более чем в 2 раза отличающуюся от текущего размера). &amp;lt;math&amp;gt;N_0&amp;lt;/math&amp;gt; - это число входных точек, загруженных в память с пороговым ограничением &amp;lt;math&amp;gt;T_0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Соответственно, итоговая сложность фазы 1 &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P})+log_2\frac{N}{N_0}*d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Анализ фазы 2 проводится аналогично.&lt;br /&gt;
&lt;br /&gt;
Что касается операций ввода-вывода, то в фазе 1 данные сканируются один раз, а в фазе 2 не сканируются вовсе.&lt;br /&gt;
Некоторое количество вычислений связано с удалением точек из областей с низкой плотностью.&lt;br /&gt;
Если количество доступной для этой операции памяти не больше &#039;&#039;M&#039;&#039; и проведено порядка &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; перестроек дерева, то сложность ввода-вывода для фазы 1 существенно не отличается от сложности чтения из файла. Основываясь рассуждениях выше, сложность фаз 1 и 2 будет линейно увеличиваться с ростом N.&lt;br /&gt;
&lt;br /&gt;
В фазе 3 нет операций ввода-вывода. Её сложность ограничена константой, которая зависит от максимального размера входных данных, и варианта выбранного алгоритма для кластеризации. &lt;br /&gt;
&lt;br /&gt;
Фаза 4 снова сканирует данные и записывает каждую точку в подходящий кластер; время работы пропорционально &amp;lt;math&amp;gt;N*K&amp;lt;/math&amp;gt;.   &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
=== Вычисление расстояния ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2=\frac{N_1*SS_2+N_2*SS_1-2*\vec{LS_1}*\vec{LS_2}}{N_1*N_2}&amp;lt;/math&amp;gt;, где&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF_1=[N_1,\vec{LS_1},SS_1]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF_2=[N_2,\vec{LS_2},SS_2]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:ZgYL51QJsQk.jpg|500px|thumb|center|alt text]]&lt;br /&gt;
&amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельно могут быть выполнены следующие шаги алгоритма:&lt;br /&gt;
* Нахождение ближайшего к новому элементу подкластера в узле при выполнении операции вставки. Это возможно за счет того, что расстояние между парами элементов может быть вычислено независимо друг от друга. Сложность &lt;br /&gt;
* Вычисление величин &amp;lt;math&amp;gt;\vec{LS},\vec{X0}, R, D, D_0-D_4&amp;lt;/math&amp;gt;, в процессе чего выполняются операции сложения и скалярного произведения векторов.&lt;br /&gt;
&lt;br /&gt;
Другим способом параллелизации алгоритма может служить создание и заполнение сразу множества кластерных деревьев, между которыми будут распределены входные данные. Множество всех подкластеров листьевых узлов полученных таким образом деревьев может быть подвергнуто глобальной кластеризации с помощью какого-либо из известных параллельных алгоритмов, например, k-средних&amp;lt;ref&amp;gt;[http://people.du.ac.in/~ngupta/Publications/PBIRCH%20A%20Sacalabel%20Paralllel%20Clustering.pdf A Garg, N Gupta PBIRCH: A Scalable Parallel Clustering algorithm for Incremental Data]&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;
* Набор из &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек &amp;lt;math&amp;gt;\{X_i\}, i=1,...,N&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Кластерное дерево с не более чем &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt; узлами.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Достоинства алгоритма ===&lt;br /&gt;
По сравнению с предыдущими методами BIRCH обладает следующими достоинствами:&lt;br /&gt;
&lt;br /&gt;
1. BIRCH является локальным алгоритмом, то есть каждое решение о каждом элементе кластера принимается без повторного сканирования данных или уже существующих кластеров. Используются только метрики, отражающие близость элементов друг к другу.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH использует факт неравномерного распределения данных в пространстве и поэтому не все данные рассматриваются как одинаково важные для построения кластера. Области с большой плотностью обрабатываются как единый кластер. Данные в более разреженных областях могут удаляться (опционально).&lt;br /&gt;
&lt;br /&gt;
3. BIRCH использует всю доступную память для получения наилучших из возможных подкластеров, в то же время минимизируя затраты на операции ввода/вывода. Оптимизация процесса кластеризации достигается за счет использования взвешенно-сбалансированного дерева. При этом время исполнения линейно.&lt;br /&gt;
&lt;br /&gt;
4. BIRCH не требует всего набора данных заранее (при этом просматривает его всего один раз).&lt;br /&gt;
&lt;br /&gt;
=== Недостатки алгоритма ===&lt;br /&gt;
&lt;br /&gt;
1. Алгоритм позволяет работать только с числовыми данными.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH хорошо выделяет только кластеры сферической формы.&lt;br /&gt;
&lt;br /&gt;
3. Существует необходимость в задании пороговых значений.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
В составе пакетов и библиотек:&lt;br /&gt;
* [http://scikit-learn.org/stable/modules/generated/sklearn.cluster.Birch.html scikit-learn]&lt;br /&gt;
* [http://cucis.ece.northwestern.edu/projects/DMS/MineBench.html NU-MineBench]&lt;br /&gt;
Пользовательские реализации:&lt;br /&gt;
* [https://code.google.com/archive/p/jbirch/ JBIRCH]&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Светлана Морозова</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13835</id>
		<title>Участник:Smirnov.maxim/BIRCH</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13835"/>
		<updated>2016-10-26T07:26:03Z</updated>

		<summary type="html">&lt;p&gt;Светлана Морозова: /* Вычисление расстояния */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Авторы: [[Участник:Светлана Морозова|Морозова Светлана]], [[Участник:Smirnov.maxim|Смирнов Максим]].&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Нахождение полезных для анализа закономерностей в больших объёмах данных с недавних пор вызывает значительный интерес. В связи с этим ввелось и стало активно развиваться такое понятие как &#039;&#039;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7 кластеризация]&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Ранние работы и алгоритмы, разработанные в этой области, не уделяли достаточного внимания анализу очень больших наборов данных или минимизации издержек на процессы ввода-вывода.&lt;br /&gt;
Решением этих проблем стал алгоритм, известный как BIRCH.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIRCH&#039;&#039;&#039;&amp;lt;ref&amp;gt;[http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf Нейский И.М. Классификация и сравнение методов кластеризации]&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;[http://www.cs.sfu.ca/CourseCentral/459/han/papers/zhang96.pdf T Zhang, R Ramakrishnan, M Livny. BIRCH: An Efficient Data Clustering Method for Very Large Databases]&amp;lt;/ref&amp;gt; (balanced iterative reducing and clustering using hierarchies)- алгоритм, применяемый в области [https://ru.wikipedia.org/wiki/Data_mining Data mining] и использующий принципы [https://ru.wikipedia.org/wiki/%D0%98%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F иерархической кластеризации].&lt;br /&gt;
&lt;br /&gt;
Если имеется очень большой набор данных, то в пространстве он распределен, как правило, неравномерно. Кластерный анализ определяет места наибольшего и наименьшего скоплений, чтобы таким образом понять всю картину целиком. Кроме того, полученные кластеры визуализируются гораздо нагляднее, чем начальные &amp;quot;сырые&amp;quot; данные.&lt;br /&gt;
Задачей алгоритмов кластеризации является не только простое разбиение данных на кластеры, но и работа в рамках ограниченного объёма доступной памяти (как правило, её объём гораздо меньше, чем размер исходного набора данных) и минимизация времени, требуемого на операции ввода-вывода.&lt;br /&gt;
&lt;br /&gt;
Для наилучшего решения этих проблем BIRCH распределяет входящие данные по кластерам динамически. Для эффективной кластеризации алгоритму требуется всего одно сканирование данных (т.е. с увеличением количества данных сложность увеличивается линейно). А при помощи одной (или более) дополнительных итераций можно и далее улучшать эффективность. BIRCH также является первым алгоритмом, предложенным для эффективного управления &amp;quot;шумами&amp;quot; (данными, которые не вписываются в общее представление модели).&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Теоретическая основа ===&lt;br /&gt;
&lt;br /&gt;
Пусть в кластере имеются &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}, i=1,2,...,N&amp;lt;/math&amp;gt;.&lt;br /&gt;
Тогда &#039;&#039;&#039;центроид&#039;&#039;&#039; &amp;lt;math&amp;gt;{\vec{{X_0}}}&amp;lt;/math&amp;gt;, &#039;&#039;&#039;радиус&#039;&#039;&#039; &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &#039;&#039;&#039;диаметр&#039;&#039;&#039; &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластера определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;{\vec{X_0}}=\frac{\sum_{i=1}^N\vec{X_i}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{\sum_{i=1}^N{(\vec{X_i} - \vec{X_0})}^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{\sum_{i=1}^N\sum_{j=1}^N{(\vec{X_i} - \vec{X_j})}^2}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; - это среднее расстояние от каждой точки до центроида. &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; - это среднее расстояние между парами в кластере. Данные величины являются альтернативными метриками плотности кластера относительно центроида.&lt;br /&gt;
&lt;br /&gt;
Для измерения близости друг к другу двух кластеров вводятся следующие метрики:&lt;br /&gt;
&lt;br /&gt;
пусть даны центроиды двух кластеров &amp;lt;math&amp;gt;\vec{X_{01}}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\vec{X_{02}}&amp;lt;/math&amp;gt;.&lt;br /&gt;
Евклидова метрика &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt; и метрика Манхэттена &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt; между двумя кластерами определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_0 = ((\vec{X_{01}}-\vec{X_{02}})^2)^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_1 = |\vec{X_{01}}-\vec{X_{02}}| = \sum_{i=1}^d |{\vec{X_{01}}}^{(i)}-{\vec{X_{02}}}^{(i)}| &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть имеются два кластера, содержащих соответственно  &amp;lt;math&amp;gt;N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;N_2&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i= 1,2, ...,N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\{\vec{X_j}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j= N_1+1,N_1+2, ...,N_1+N_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Среднее расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &#039;&#039;&#039;среднее внутрикластерное расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &#039;&#039;&#039;дисперсия&#039;&#039;&#039; &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; для двух кластеров определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{\sum_{i=1}^{N_1}\sum_{j=N_1+1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{N_1N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{\sum_{i=1}^{N_1+N_2}\sum_{j=1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_4 = \sum_{k=1}^{N_1+N_2}(\vec{X_k} - \frac{\sum_{i=1}^{N_1+N_2}\vec{X_i}}{N_1+N_2})^2 - \sum_{i=1}^{N_1}(\vec{X_i} - \frac{\sum_{i=1}^{N_1}\vec{X_i}}{N_1})^2 - \sum_{j=N_1+1}^{N_1+N_2}(\vec{X_j} - \frac{\sum_{i=N_1+1}^{N_1+N_2}\vec{X_i}}{N_2})^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Таким образом, величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; относятся к отдельным кластерам, а &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; - к объединению двух кластеров.&lt;br /&gt;
&lt;br /&gt;
=== Кластерный элемент и кластерное дерево ===&lt;br /&gt;
&lt;br /&gt;
В основе концепции алгоритма BIRCH лежат понятия &#039;&#039;&#039;кластерного элемента&#039;&#039;&#039; и &#039;&#039;&#039;кластерного дерева (CF Tree)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====Кластерный элемент ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; Пусть в кластере содержатся  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности  &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;:&amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;i=1,2,...,N&amp;lt;/math&amp;gt;. &lt;br /&gt;
&#039;&#039;&#039;Кластерный элемент (CF)&#039;&#039;&#039; - тройка чисел, характеризующая информацию о кластере: &lt;br /&gt;
&amp;lt;math&amp;gt;CF = (N, \vec{LS}, SS)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - количество элементов входных данных, содержащихся в кластере, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; - линейная сумма входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}\vec{X_i}&amp;lt;/math&amp;gt;), &amp;lt;math&amp;gt;SS&amp;lt;/math&amp;gt; - сумма квадратов входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}{\vec{X_i}}^2&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Теорема&#039;&#039;&#039; Пусть &amp;lt;math&amp;gt;CF_1 = (N_1, \vec{LS_1}, SS_1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;CF_2 = (N_1, \vec{LS_2}, SS_2)&amp;lt;/math&amp;gt; - CF векторы двух непересекающихся кластеров. Тогда при их объединении образуется кластер со следующим CF вектором: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF = CF_1 + CF_2 = (N_1+N_2, \vec{LS_1}+\vec{LS_2}, SS_1+SS_2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Из указанных выше определения и теоремы вытекает тот факт, что при объединении кластеров их CF вектор может вычисляться инкрементно и точно. &lt;br /&gt;
Легко показать, что вычислить величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;, как и обычные метрики, также не составит труда.&lt;br /&gt;
&lt;br /&gt;
Таким образом, в данном случае информацией о кластере является не весь набор точек, а вектор CF. Хранение одного только вектора может показаться неэффективным, но этого вполне достаточно для оперирования всеми необходимыми метриками, на основе которых принимаются решения в алгоритме BIRCH.&lt;br /&gt;
&lt;br /&gt;
==== Кластерное дерево ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; &#039;&#039;&#039;Кластерное дерево (CF Tree)&#039;&#039;&#039; - это взвешенно сбалансированное дерево с двумя параметрами: &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - коэффициент разветвления, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - пороговая величина.&lt;br /&gt;
&lt;br /&gt;
Каждый нелистьевой узел дерева имеет не более чем &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; вхождений узлов следующей формы: &amp;lt;math&amp;gt;[CF_i,child_i]&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i=1,2,...,B&amp;lt;/math&amp;gt;, &#039;&#039;child&#039;&#039; - указатель на i-й дочерний узел, &amp;lt;math&amp;gt;CF_i&amp;lt;/math&amp;gt; - CF вектор соответствующего подкластера.&lt;br /&gt;
&lt;br /&gt;
Каждый листьевой узел имеет ссылку на два соседних узла (&#039;&#039;prev&#039;&#039; и &#039;&#039;next&#039;&#039;) для того, чтобы связать все узлы для эффективного сканирования.&lt;br /&gt;
Все листьевые узлы должны удовлетворять пороговому ограничению &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, т.е. диаметр (радиус) не должен превосходить &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;.&lt;br /&gt;
В процессе вставки новых данных CF дерево строится динамически. Оно использует вставку данных для кластеризации точно также как &amp;lt;math&amp;gt;B+&amp;lt;/math&amp;gt; [https://ru.wikipedia.org/wiki/B%2B-%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE дерево] использует её для поиска.&lt;br /&gt;
CF дерево очень компактно, поскольку каждый листьевой узел - это не просто точка, а подкластер (который объединяет множество точек с учётом ограничения &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Операция вставки в &#039;&#039;&#039;CF&#039;&#039;&#039; дерево ====&lt;br /&gt;
&lt;br /&gt;
Опишем алгоритм вставки элемнта &amp;lt;math&amp;gt;Ent&amp;lt;/math&amp;gt; в CF дерево:&lt;br /&gt;
&lt;br /&gt;
1) &#039;&#039;Определение подходящего листа&#039;&#039;: Начиная с корня, алгоритм рекурсивно спускается по CF дереву, выбирая &#039;&#039;&#039;ближайший&#039;&#039;&#039; дочерний узел в соответствии с выбранной метрикой &amp;lt;math&amp;gt;D0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D4&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &#039;&#039;Преобразование листа&#039;&#039;: Когда алгоритм доходит до листа, он находит ближайшую листьевой элемент, скажем, &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;, а затем проверяет, можно ли добавить &#039;&#039;Ent&#039;&#039; к &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt; без нарушения порогового условия. Если да, то с учётом этого изменяется CF вектор для &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;; если нет, то &#039;&#039;Ent&#039;&#039; становится новым элементом листа. Если в листе для этого достаточно места, то шаг окончен, иначе он должен &amp;quot;расщепиться&amp;quot;. Расщепление узла производится при помощи выбора за основу наиболее удалённой друг от друга пары элементов и перераспределение оставшихся элементов в соответствии с выбранным критерием близости.&lt;br /&gt;
&lt;br /&gt;
3) &#039;&#039;Преобразование пути к листу&#039;&#039;: После вставки &#039;&#039;Ent&#039;&#039; в лист мы должны обновить информацию о CF для каждого нелистьевого элемента на пути к листу. При отсутствии расщепления это означает простое сложение CF векторов для отражения факта добавления &#039;&#039;Ent&#039;&#039;. Расщепление листа же требует вставки нового нелистьевого элемента в родительский узел для задания только что созданного листа. Если у родителя есть место для этого элемента, то необходимо просто преобразовать CF векторы на всех более высоких уровнях. В общем случае, однако, нам также придётся расщепить родительский узел, и так далее до корня. Если расщеплён корень, то высота дерева увеличивается на единицу.&lt;br /&gt;
&lt;br /&gt;
4) &#039;&#039;Улучшение слияния&#039;&#039;: Расщепление вызвано ограничением на размер узла, который не зависит от кластеризационных свойств данных. Если во входящем потоке присутствуют &amp;quot;искажённые&amp;quot; (из областей с низкой плотностью) данные, это может повлиять на качество кластеризации, а также уменьшить эффективность использования памяти. Дополнительный шаг алгоритма помогает решить эти проблемы: предположим, что произошло расщепление листа, и распространение этого процесса остановилось на некотором нелистьевом узле &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt;, то есть &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; может вместить дополнительный элемент, полученный после расщепления. Теперь мы сканируем узел &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; для нахождения двух наиболее близких элементов. Если это не пара, отвечающая расщеплению, мы пытаемся объединить их и поставить в соответствие два дочерних узла. Если количество элементов в дочерних узлах  больше B, мы снова расщепляем результат объединения.&lt;br /&gt;
В процессе повторного расщепления, в случае, если один источник собирает достаточно элементов для того, чтобы полностью заполнить узел, оставшиеся элементы передаются другом источнику. В итоге, если объединённые элементы помещаются в одном узле, в нём освобождается место для ещё одного элемента. Тем самым увеличивается степень использования свободного пространства и откладывается дальнейшее расщепление. В ином случае мы улучшаем распределение элементов в двух ближайших подкластерах.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро алгоритма заключается в многократном выполнении операции вставки нового элемента в дерево, в процессе чего требуется вычисление следующих величин:&lt;br /&gt;
&lt;br /&gt;
* радиуса &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; или диаметра &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластерного элемента. Выполняется при попытке вставить новый элемент в один из подкластеров листьевого узла дерева.&lt;br /&gt;
&lt;br /&gt;
* расстояния между двумя элементами. Выполняется при поиске ближайшего по отношению к новому элементу подкластера в узле дерева по одной из рассмотренных в разд. 1.2.1 метрик &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Зная характеристики кластерных элементов &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;, в результате алгебраических преобразований можно получить следующие упрощенные формулы вычисления необходимых значений:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\vec{X_0} = \frac{\vec{LS}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{SS - 2\vec{X_0}\vec{LS} + N(\vec{X_0})^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{2(N*SS - (\vec{LS})^2)}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{N_1*SS_2 + N_2*SS_1 - 2\vec{LS_1}\vec{LS_2}}{N_1*N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{2((N_1+N_2)(SS_1+SS_2)-(\vec{LS_1}+\vec{LS_2})^2)}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Реализация алгоритма BIRCH состояит из следующих четырёх фаз:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 1&#039;&#039;&#039;. Главной задачей фазы 1 является сканирование всех данных и построение в памяти исходного CF дерева, используя заданное количество памяти. Это дерево стремится отразить информацию о кластеризации данных настолько хорошо, насколько это позволяют ограничения по памяти. При этом плотно распределённые данные группируются в подкластеры, а более разрозненные данные удаляются. После завершения фазы 1 вспомогательные вычисления в дальнейших фазах будут:&lt;br /&gt;
&lt;br /&gt;
1) быстрее, потому что (а) больше не нужны операции ввода-вывода, (b) проблема кластеризации начальных данных упрощается до проблемы кластеризации подкластеров в листьях;&lt;br /&gt;
&lt;br /&gt;
2) точнее, потому что (а) большинство данных с низкой плотностью удалены, (b) оставшиеся данные распределены оптимально (в соответствии с доступным количеством памяти);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 2&#039;&#039;&#039;. Данная фаза является опциональной. Известно, что существующие методы глобальной кластеризации, используемые в рамках фазы 3, имеют различные диапазоны входных значений, при которых их реализация наиболее эффективна. Поэтому потенциально существует пробел между размером фазы 1 и входными значениями фазы 3. И фаза 2 как раз является недостающим связующим звеном: так же как и фаза 1, она сканирует листьевые элементы начального CF дерева для того, чтобы построить меньшее дерево, удаляя ещё больше элементов с низкой плотностью и группируя переполненные подкластеры в большие кластеры.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 3&#039;&#039;&#039;. В данной фазе для листьевых элементов применяется (любой подходящий) алгоритм глобальной кластеризации. Существующие алгоритмы кластеризации наборов точек могут также работать с наборами подкластеров, каждый из которых представлен своим CF вектором. Зная CF вектор, можно вычислить центроид и в дальнейшем заменить всю информацию о кластере этим значением (этого достаточно для вычисления большинства необходимых метрик). После фазы 3 мы получаем набор кластеров, который отражает основные характеристики распределяемых данных.&lt;br /&gt;
Однако, всё ещё могут оставаться некоторые неточности, для устранения которых существует фаза 4.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 4&#039;&#039;&#039;. Данная фаза является опциональной и влечёт за собой затраты на дополнительное сканирование данных для корректировки неточностей и дальнейшего улучшения кластеризации. Фаза 4 использует центроиды кластеров, полученные в фазе 3 для как основы и перераспределяет точки входных данных в ближайшие для них основы для получения нового списка кластеров. Фаза 4, если это необходимо пользователю, может быть расширена дополнительными проходами для уверенности в том, что результат приближается к оптимальному.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Последовательную реализацию основных операций алгоритма BIRCH можно продемонстрировать на примере следующего фрагмента кода на языке C++:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot;&amp;gt;&lt;br /&gt;
void CF_Node::insert(const CF_Cluster &amp;amp;entry)&lt;br /&gt;
{&lt;br /&gt;
    //Находим ближайший к новому элементу подкластер в узле&lt;br /&gt;
    СF_Vector_it closest = entry.findClosest(subclusters);&lt;br /&gt;
    //Если узел пустой, добавляем в него новый подкластер&lt;br /&gt;
    if (closest == subclusters.end()) {&lt;br /&gt;
        subclusters.push_back(entry);&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    closest-&amp;gt;add(entry);&lt;br /&gt;
    //Если узел является листьевым, и ближайший подкластер не может вместить&lt;br /&gt;
    //новый элемент, добавляем в узел новый подкластер&lt;br /&gt;
    if (leaf) {&lt;br /&gt;
        if (closest-&amp;gt;D &amp;gt; threshold) {&lt;br /&gt;
            closest-&amp;gt;remove(entry);&lt;br /&gt;
            subclusters.push_back(entry);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else {&lt;br /&gt;
        CF_Node *node = closest-&amp;gt;child;&lt;br /&gt;
        node-&amp;gt;insert(entry);&lt;br /&gt;
        //Если при добавлении нового элемента в дочерний узел тот переполнился,&lt;br /&gt;
        //расщепляем его        &lt;br /&gt;
        if (node-&amp;gt;getSubclusters().size() &amp;gt; bFactor) {&lt;br /&gt;
            CF_Vector newClusters = node-&amp;gt;splitNode();&lt;br /&gt;
            delete node;&lt;br /&gt;
            subclusters.erase(closest);&lt;br /&gt;
            subclusters.insert(subclusters.end(), newClusters.begin(), newClusters.end());&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    //Если узел является корневым и он переполнен, расщепляем его&lt;br /&gt;
    if (root &amp;amp;&amp;amp; subclusters.size() &amp;gt; bFactor) {&lt;br /&gt;
        subclusters = splitNode();&lt;br /&gt;
        leaf = false;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
CF_Vector CF_Node::splitNode()&lt;br /&gt;
{&lt;br /&gt;
    if (subclusters.size() &amp;lt; 2)&lt;br /&gt;
        return (root) ? subclusters : CF_Vector{CF_Cluster(this)};&lt;br /&gt;
    //Находим пару наиболее удаленных друг от друга подкластеров&lt;br /&gt;
    CF_Vector_it pole1, pole2;&lt;br /&gt;
    data_t longestDist = 0.0;&lt;br /&gt;
    for (auto lhs = subclusters.begin(); lhs != subclusters.end() - 1; ++lhs) {&lt;br /&gt;
        for (auto rhs = lhs + 1; rhs != subclusters.end(); ++rhs) {&lt;br /&gt;
            auto distance = getDistance(*lhs, *rhs);&lt;br /&gt;
            if (distance &amp;gt; longestDist) {&lt;br /&gt;
                longestDist = distance;&lt;br /&gt;
                pole1 = lhs;&lt;br /&gt;
                pole2 = rhs;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    //Разделяем множество всех подкластеров узла на две части&lt;br /&gt;
    CF_Vector subclusters1, subclusters2;&lt;br /&gt;
    for (auto it = subclusters.begin(); it != subclusters.end(); ++it) {&lt;br /&gt;
        if (getDistance(*it, *pole1) &amp;lt; getDistance(*it, *pole2))&lt;br /&gt;
            subclusters1.push_back(*it);&lt;br /&gt;
        else&lt;br /&gt;
            subclusters2.push_back(*it);&lt;br /&gt;
    }&lt;br /&gt;
    //Создаем два новых узла&lt;br /&gt;
    CF_Node *node1 = new CF_Node(threshold, bFactor, count, leaf, subclusters1),&lt;br /&gt;
            *node2 = new CF_Node(threshold, bFactor, count, leaf, subclusters2);&lt;br /&gt;
    //Связываем листья&lt;br /&gt;
    if (leaf) {&lt;br /&gt;
        if (prevLeaf) {&lt;br /&gt;
            node1-&amp;gt;setPrevLeaf(prevLeaf);&lt;br /&gt;
            prevLeaf-&amp;gt;setNextLeaf(node1);&lt;br /&gt;
        }&lt;br /&gt;
        if (nextLeaf) {&lt;br /&gt;
            node2-&amp;gt;setNextLeaf(nextLeaf);&lt;br /&gt;
            nextLeaf-&amp;gt;setPrevLeaf(node2);&lt;br /&gt;
        }&lt;br /&gt;
        node1-&amp;gt;setNextLeaf(node2);&lt;br /&gt;
        node2-&amp;gt;setPrevLeaf(node1);&lt;br /&gt;
    }&lt;br /&gt;
    CF_Cluster cluster1(node1), cluster2(node2);&lt;br /&gt;
    return CF_Vector{cluster1, cluster2};&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Для начала проанализируем вычислительную сложность фазы 1.&lt;br /&gt;
Максимальный размер дерева &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt; - ограничение по памяти на размер узла, а &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - общий объем памяти. Для того чтобы вставить элемент, мы должны пройти путь от корня до листа (это около &amp;lt;math&amp;gt;1+log_B\frac{M}{P}&amp;lt;/math&amp;gt; узлов). В каждом узле в поисках &amp;quot;ближайшего&amp;quot; нам необходимо просмотреть B элементов; сложность для каждого элемента пропорциональна размерности &#039;&#039;d&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Поэтому сложность вставки всех входных точек &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В случае, когда необходимо перестроить дерево, предположим, что ES - это размер CF элемента. Существует максимум &amp;lt;math&amp;gt;\frac{M}{ES}&amp;lt;/math&amp;gt; листьевых элементов для вставки, поэтому сложность повторной вставки листьевых элементов &amp;lt;math&amp;gt;O(d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Количество итераций перестройки дерева зависит от пороговой величины. На самом деле, это около &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; (двоичное основание появилось из-за того, что мы не можем провести оценку более чем в 2 раза отличающуюся от текущего размера). &amp;lt;math&amp;gt;N_0&amp;lt;/math&amp;gt; - это число входных точек, загруженных в память с пороговым ограничением &amp;lt;math&amp;gt;T_0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Соответственно, итоговая сложность фазы 1 &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P})+log_2\frac{N}{N_0}*d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Анализ фазы 2 проводится аналогично.&lt;br /&gt;
&lt;br /&gt;
Что касается операций ввода-вывода, то в фазе 1 данные сканируются один раз, а в фазе 2 не сканируются вовсе.&lt;br /&gt;
Некоторое количество вычислений связано с удалением точек из областей с низкой плотностью.&lt;br /&gt;
Если количество доступной для этой операции памяти не больше &#039;&#039;M&#039;&#039; и проведено порядка &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; перестроек дерева, то сложность ввода-вывода для фазы 1 существенно не отличается от сложности чтения из файла. Основываясь рассуждениях выше, сложность фаз 1 и 2 будет линейно увеличиваться с ростом N.&lt;br /&gt;
&lt;br /&gt;
В фазе 3 нет операций ввода-вывода. Её сложность ограничена константой, которая зависит от максимального размера входных данных, и варианта выбранного алгоритма для кластеризации. &lt;br /&gt;
&lt;br /&gt;
Фаза 4 снова сканирует данные и записывает каждую точку в подходящий кластер; время работы пропорционально &amp;lt;math&amp;gt;N*K&amp;lt;/math&amp;gt;.   &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
=== Вычисление расстояния ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2=\frac{N_1*SS_2+N_2*SS_1-2*\vec{LS_1}*\vec{LS_2}}{N_1*N_2}&amp;lt;/math&amp;gt;, где&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF_1=[N_1,\vec{LS_1},SS_1]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF_2=[N_2,\vec{LS_2},SS_2]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:ZgYL51QJsQk.jpg|200px|thumb|left|alt text]]&lt;br /&gt;
&amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельно могут быть выполнены следующие шаги алгоритма:&lt;br /&gt;
* Нахождение ближайшего к новому элементу подкластера в узле при выполнении операции вставки. Это возможно за счет того, что расстояние между парами элементов может быть вычислено независимо друг от друга. Сложность &lt;br /&gt;
* Вычисление величин &amp;lt;math&amp;gt;\vec{LS},\vec{X0}, R, D, D_0-D_4&amp;lt;/math&amp;gt;, в процессе чего выполняются операции сложения и скалярного произведения векторов.&lt;br /&gt;
&lt;br /&gt;
Другим способом параллелизации алгоритма может служить создание и заполнение сразу множества кластерных деревьев, между которыми будут распределены входные данные. Множество всех подкластеров листьевых узлов полученных таким образом деревьев может быть подвергнуто глобальной кластеризации с помощью какого-либо из известных параллельных алгоритмов, например, k-средних&amp;lt;ref&amp;gt;[http://people.du.ac.in/~ngupta/Publications/PBIRCH%20A%20Sacalabel%20Paralllel%20Clustering.pdf A Garg, N Gupta PBIRCH: A Scalable Parallel Clustering algorithm for Incremental Data]&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;
* Набор из &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек &amp;lt;math&amp;gt;\{X_i\}, i=1,...,N&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Кластерное дерево с не более чем &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt; узлами.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Достоинства алгоритма ===&lt;br /&gt;
По сравнению с предыдущими методами BIRCH обладает следующими достоинствами:&lt;br /&gt;
&lt;br /&gt;
1. BIRCH является локальным алгоритмом, то есть каждое решение о каждом элементе кластера принимается без повторного сканирования данных или уже существующих кластеров. Используются только метрики, отражающие близость элементов друг к другу.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH использует факт неравномерного распределения данных в пространстве и поэтому не все данные рассматриваются как одинаково важные для построения кластера. Области с большой плотностью обрабатываются как единый кластер. Данные в более разреженных областях могут удаляться (опционально).&lt;br /&gt;
&lt;br /&gt;
3. BIRCH использует всю доступную память для получения наилучших из возможных подкластеров, в то же время минимизируя затраты на операции ввода/вывода. Оптимизация процесса кластеризации достигается за счет использования взвешенно-сбалансированного дерева. При этом время исполнения линейно.&lt;br /&gt;
&lt;br /&gt;
4. BIRCH не требует всего набора данных заранее (при этом просматривает его всего один раз).&lt;br /&gt;
&lt;br /&gt;
=== Недостатки алгоритма ===&lt;br /&gt;
&lt;br /&gt;
1. Алгоритм позволяет работать только с числовыми данными.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH хорошо выделяет только кластеры сферической формы.&lt;br /&gt;
&lt;br /&gt;
3. Существует необходимость в задании пороговых значений.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
В составе пакетов и библиотек:&lt;br /&gt;
* [http://scikit-learn.org/stable/modules/generated/sklearn.cluster.Birch.html scikit-learn]&lt;br /&gt;
* [http://cucis.ece.northwestern.edu/projects/DMS/MineBench.html NU-MineBench]&lt;br /&gt;
Пользовательские реализации:&lt;br /&gt;
* [https://code.google.com/archive/p/jbirch/ JBIRCH]&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Светлана Морозова</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13834</id>
		<title>Участник:Smirnov.maxim/BIRCH</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13834"/>
		<updated>2016-10-26T07:25:10Z</updated>

		<summary type="html">&lt;p&gt;Светлана Морозова: /* Вычисление расстояния */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Авторы: [[Участник:Светлана Морозова|Морозова Светлана]], [[Участник:Smirnov.maxim|Смирнов Максим]].&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Нахождение полезных для анализа закономерностей в больших объёмах данных с недавних пор вызывает значительный интерес. В связи с этим ввелось и стало активно развиваться такое понятие как &#039;&#039;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7 кластеризация]&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Ранние работы и алгоритмы, разработанные в этой области, не уделяли достаточного внимания анализу очень больших наборов данных или минимизации издержек на процессы ввода-вывода.&lt;br /&gt;
Решением этих проблем стал алгоритм, известный как BIRCH.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIRCH&#039;&#039;&#039;&amp;lt;ref&amp;gt;[http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf Нейский И.М. Классификация и сравнение методов кластеризации]&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;[http://www.cs.sfu.ca/CourseCentral/459/han/papers/zhang96.pdf T Zhang, R Ramakrishnan, M Livny. BIRCH: An Efficient Data Clustering Method for Very Large Databases]&amp;lt;/ref&amp;gt; (balanced iterative reducing and clustering using hierarchies)- алгоритм, применяемый в области [https://ru.wikipedia.org/wiki/Data_mining Data mining] и использующий принципы [https://ru.wikipedia.org/wiki/%D0%98%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F иерархической кластеризации].&lt;br /&gt;
&lt;br /&gt;
Если имеется очень большой набор данных, то в пространстве он распределен, как правило, неравномерно. Кластерный анализ определяет места наибольшего и наименьшего скоплений, чтобы таким образом понять всю картину целиком. Кроме того, полученные кластеры визуализируются гораздо нагляднее, чем начальные &amp;quot;сырые&amp;quot; данные.&lt;br /&gt;
Задачей алгоритмов кластеризации является не только простое разбиение данных на кластеры, но и работа в рамках ограниченного объёма доступной памяти (как правило, её объём гораздо меньше, чем размер исходного набора данных) и минимизация времени, требуемого на операции ввода-вывода.&lt;br /&gt;
&lt;br /&gt;
Для наилучшего решения этих проблем BIRCH распределяет входящие данные по кластерам динамически. Для эффективной кластеризации алгоритму требуется всего одно сканирование данных (т.е. с увеличением количества данных сложность увеличивается линейно). А при помощи одной (или более) дополнительных итераций можно и далее улучшать эффективность. BIRCH также является первым алгоритмом, предложенным для эффективного управления &amp;quot;шумами&amp;quot; (данными, которые не вписываются в общее представление модели).&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Теоретическая основа ===&lt;br /&gt;
&lt;br /&gt;
Пусть в кластере имеются &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}, i=1,2,...,N&amp;lt;/math&amp;gt;.&lt;br /&gt;
Тогда &#039;&#039;&#039;центроид&#039;&#039;&#039; &amp;lt;math&amp;gt;{\vec{{X_0}}}&amp;lt;/math&amp;gt;, &#039;&#039;&#039;радиус&#039;&#039;&#039; &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &#039;&#039;&#039;диаметр&#039;&#039;&#039; &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластера определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;{\vec{X_0}}=\frac{\sum_{i=1}^N\vec{X_i}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{\sum_{i=1}^N{(\vec{X_i} - \vec{X_0})}^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{\sum_{i=1}^N\sum_{j=1}^N{(\vec{X_i} - \vec{X_j})}^2}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; - это среднее расстояние от каждой точки до центроида. &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; - это среднее расстояние между парами в кластере. Данные величины являются альтернативными метриками плотности кластера относительно центроида.&lt;br /&gt;
&lt;br /&gt;
Для измерения близости друг к другу двух кластеров вводятся следующие метрики:&lt;br /&gt;
&lt;br /&gt;
пусть даны центроиды двух кластеров &amp;lt;math&amp;gt;\vec{X_{01}}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\vec{X_{02}}&amp;lt;/math&amp;gt;.&lt;br /&gt;
Евклидова метрика &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt; и метрика Манхэттена &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt; между двумя кластерами определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_0 = ((\vec{X_{01}}-\vec{X_{02}})^2)^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_1 = |\vec{X_{01}}-\vec{X_{02}}| = \sum_{i=1}^d |{\vec{X_{01}}}^{(i)}-{\vec{X_{02}}}^{(i)}| &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть имеются два кластера, содержащих соответственно  &amp;lt;math&amp;gt;N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;N_2&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i= 1,2, ...,N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\{\vec{X_j}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j= N_1+1,N_1+2, ...,N_1+N_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Среднее расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &#039;&#039;&#039;среднее внутрикластерное расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &#039;&#039;&#039;дисперсия&#039;&#039;&#039; &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; для двух кластеров определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{\sum_{i=1}^{N_1}\sum_{j=N_1+1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{N_1N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{\sum_{i=1}^{N_1+N_2}\sum_{j=1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_4 = \sum_{k=1}^{N_1+N_2}(\vec{X_k} - \frac{\sum_{i=1}^{N_1+N_2}\vec{X_i}}{N_1+N_2})^2 - \sum_{i=1}^{N_1}(\vec{X_i} - \frac{\sum_{i=1}^{N_1}\vec{X_i}}{N_1})^2 - \sum_{j=N_1+1}^{N_1+N_2}(\vec{X_j} - \frac{\sum_{i=N_1+1}^{N_1+N_2}\vec{X_i}}{N_2})^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Таким образом, величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; относятся к отдельным кластерам, а &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; - к объединению двух кластеров.&lt;br /&gt;
&lt;br /&gt;
=== Кластерный элемент и кластерное дерево ===&lt;br /&gt;
&lt;br /&gt;
В основе концепции алгоритма BIRCH лежат понятия &#039;&#039;&#039;кластерного элемента&#039;&#039;&#039; и &#039;&#039;&#039;кластерного дерева (CF Tree)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====Кластерный элемент ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; Пусть в кластере содержатся  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности  &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;:&amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;i=1,2,...,N&amp;lt;/math&amp;gt;. &lt;br /&gt;
&#039;&#039;&#039;Кластерный элемент (CF)&#039;&#039;&#039; - тройка чисел, характеризующая информацию о кластере: &lt;br /&gt;
&amp;lt;math&amp;gt;CF = (N, \vec{LS}, SS)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - количество элементов входных данных, содержащихся в кластере, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; - линейная сумма входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}\vec{X_i}&amp;lt;/math&amp;gt;), &amp;lt;math&amp;gt;SS&amp;lt;/math&amp;gt; - сумма квадратов входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}{\vec{X_i}}^2&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Теорема&#039;&#039;&#039; Пусть &amp;lt;math&amp;gt;CF_1 = (N_1, \vec{LS_1}, SS_1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;CF_2 = (N_1, \vec{LS_2}, SS_2)&amp;lt;/math&amp;gt; - CF векторы двух непересекающихся кластеров. Тогда при их объединении образуется кластер со следующим CF вектором: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF = CF_1 + CF_2 = (N_1+N_2, \vec{LS_1}+\vec{LS_2}, SS_1+SS_2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Из указанных выше определения и теоремы вытекает тот факт, что при объединении кластеров их CF вектор может вычисляться инкрементно и точно. &lt;br /&gt;
Легко показать, что вычислить величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;, как и обычные метрики, также не составит труда.&lt;br /&gt;
&lt;br /&gt;
Таким образом, в данном случае информацией о кластере является не весь набор точек, а вектор CF. Хранение одного только вектора может показаться неэффективным, но этого вполне достаточно для оперирования всеми необходимыми метриками, на основе которых принимаются решения в алгоритме BIRCH.&lt;br /&gt;
&lt;br /&gt;
==== Кластерное дерево ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; &#039;&#039;&#039;Кластерное дерево (CF Tree)&#039;&#039;&#039; - это взвешенно сбалансированное дерево с двумя параметрами: &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - коэффициент разветвления, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - пороговая величина.&lt;br /&gt;
&lt;br /&gt;
Каждый нелистьевой узел дерева имеет не более чем &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; вхождений узлов следующей формы: &amp;lt;math&amp;gt;[CF_i,child_i]&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i=1,2,...,B&amp;lt;/math&amp;gt;, &#039;&#039;child&#039;&#039; - указатель на i-й дочерний узел, &amp;lt;math&amp;gt;CF_i&amp;lt;/math&amp;gt; - CF вектор соответствующего подкластера.&lt;br /&gt;
&lt;br /&gt;
Каждый листьевой узел имеет ссылку на два соседних узла (&#039;&#039;prev&#039;&#039; и &#039;&#039;next&#039;&#039;) для того, чтобы связать все узлы для эффективного сканирования.&lt;br /&gt;
Все листьевые узлы должны удовлетворять пороговому ограничению &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, т.е. диаметр (радиус) не должен превосходить &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;.&lt;br /&gt;
В процессе вставки новых данных CF дерево строится динамически. Оно использует вставку данных для кластеризации точно также как &amp;lt;math&amp;gt;B+&amp;lt;/math&amp;gt; [https://ru.wikipedia.org/wiki/B%2B-%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE дерево] использует её для поиска.&lt;br /&gt;
CF дерево очень компактно, поскольку каждый листьевой узел - это не просто точка, а подкластер (который объединяет множество точек с учётом ограничения &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Операция вставки в &#039;&#039;&#039;CF&#039;&#039;&#039; дерево ====&lt;br /&gt;
&lt;br /&gt;
Опишем алгоритм вставки элемнта &amp;lt;math&amp;gt;Ent&amp;lt;/math&amp;gt; в CF дерево:&lt;br /&gt;
&lt;br /&gt;
1) &#039;&#039;Определение подходящего листа&#039;&#039;: Начиная с корня, алгоритм рекурсивно спускается по CF дереву, выбирая &#039;&#039;&#039;ближайший&#039;&#039;&#039; дочерний узел в соответствии с выбранной метрикой &amp;lt;math&amp;gt;D0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D4&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &#039;&#039;Преобразование листа&#039;&#039;: Когда алгоритм доходит до листа, он находит ближайшую листьевой элемент, скажем, &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;, а затем проверяет, можно ли добавить &#039;&#039;Ent&#039;&#039; к &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt; без нарушения порогового условия. Если да, то с учётом этого изменяется CF вектор для &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;; если нет, то &#039;&#039;Ent&#039;&#039; становится новым элементом листа. Если в листе для этого достаточно места, то шаг окончен, иначе он должен &amp;quot;расщепиться&amp;quot;. Расщепление узла производится при помощи выбора за основу наиболее удалённой друг от друга пары элементов и перераспределение оставшихся элементов в соответствии с выбранным критерием близости.&lt;br /&gt;
&lt;br /&gt;
3) &#039;&#039;Преобразование пути к листу&#039;&#039;: После вставки &#039;&#039;Ent&#039;&#039; в лист мы должны обновить информацию о CF для каждого нелистьевого элемента на пути к листу. При отсутствии расщепления это означает простое сложение CF векторов для отражения факта добавления &#039;&#039;Ent&#039;&#039;. Расщепление листа же требует вставки нового нелистьевого элемента в родительский узел для задания только что созданного листа. Если у родителя есть место для этого элемента, то необходимо просто преобразовать CF векторы на всех более высоких уровнях. В общем случае, однако, нам также придётся расщепить родительский узел, и так далее до корня. Если расщеплён корень, то высота дерева увеличивается на единицу.&lt;br /&gt;
&lt;br /&gt;
4) &#039;&#039;Улучшение слияния&#039;&#039;: Расщепление вызвано ограничением на размер узла, который не зависит от кластеризационных свойств данных. Если во входящем потоке присутствуют &amp;quot;искажённые&amp;quot; (из областей с низкой плотностью) данные, это может повлиять на качество кластеризации, а также уменьшить эффективность использования памяти. Дополнительный шаг алгоритма помогает решить эти проблемы: предположим, что произошло расщепление листа, и распространение этого процесса остановилось на некотором нелистьевом узле &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt;, то есть &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; может вместить дополнительный элемент, полученный после расщепления. Теперь мы сканируем узел &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; для нахождения двух наиболее близких элементов. Если это не пара, отвечающая расщеплению, мы пытаемся объединить их и поставить в соответствие два дочерних узла. Если количество элементов в дочерних узлах  больше B, мы снова расщепляем результат объединения.&lt;br /&gt;
В процессе повторного расщепления, в случае, если один источник собирает достаточно элементов для того, чтобы полностью заполнить узел, оставшиеся элементы передаются другом источнику. В итоге, если объединённые элементы помещаются в одном узле, в нём освобождается место для ещё одного элемента. Тем самым увеличивается степень использования свободного пространства и откладывается дальнейшее расщепление. В ином случае мы улучшаем распределение элементов в двух ближайших подкластерах.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро алгоритма заключается в многократном выполнении операции вставки нового элемента в дерево, в процессе чего требуется вычисление следующих величин:&lt;br /&gt;
&lt;br /&gt;
* радиуса &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; или диаметра &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластерного элемента. Выполняется при попытке вставить новый элемент в один из подкластеров листьевого узла дерева.&lt;br /&gt;
&lt;br /&gt;
* расстояния между двумя элементами. Выполняется при поиске ближайшего по отношению к новому элементу подкластера в узле дерева по одной из рассмотренных в разд. 1.2.1 метрик &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Зная характеристики кластерных элементов &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;, в результате алгебраических преобразований можно получить следующие упрощенные формулы вычисления необходимых значений:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\vec{X_0} = \frac{\vec{LS}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{SS - 2\vec{X_0}\vec{LS} + N(\vec{X_0})^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{2(N*SS - (\vec{LS})^2)}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{N_1*SS_2 + N_2*SS_1 - 2\vec{LS_1}\vec{LS_2}}{N_1*N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{2((N_1+N_2)(SS_1+SS_2)-(\vec{LS_1}+\vec{LS_2})^2)}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Реализация алгоритма BIRCH состояит из следующих четырёх фаз:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 1&#039;&#039;&#039;. Главной задачей фазы 1 является сканирование всех данных и построение в памяти исходного CF дерева, используя заданное количество памяти. Это дерево стремится отразить информацию о кластеризации данных настолько хорошо, насколько это позволяют ограничения по памяти. При этом плотно распределённые данные группируются в подкластеры, а более разрозненные данные удаляются. После завершения фазы 1 вспомогательные вычисления в дальнейших фазах будут:&lt;br /&gt;
&lt;br /&gt;
1) быстрее, потому что (а) больше не нужны операции ввода-вывода, (b) проблема кластеризации начальных данных упрощается до проблемы кластеризации подкластеров в листьях;&lt;br /&gt;
&lt;br /&gt;
2) точнее, потому что (а) большинство данных с низкой плотностью удалены, (b) оставшиеся данные распределены оптимально (в соответствии с доступным количеством памяти);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 2&#039;&#039;&#039;. Данная фаза является опциональной. Известно, что существующие методы глобальной кластеризации, используемые в рамках фазы 3, имеют различные диапазоны входных значений, при которых их реализация наиболее эффективна. Поэтому потенциально существует пробел между размером фазы 1 и входными значениями фазы 3. И фаза 2 как раз является недостающим связующим звеном: так же как и фаза 1, она сканирует листьевые элементы начального CF дерева для того, чтобы построить меньшее дерево, удаляя ещё больше элементов с низкой плотностью и группируя переполненные подкластеры в большие кластеры.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 3&#039;&#039;&#039;. В данной фазе для листьевых элементов применяется (любой подходящий) алгоритм глобальной кластеризации. Существующие алгоритмы кластеризации наборов точек могут также работать с наборами подкластеров, каждый из которых представлен своим CF вектором. Зная CF вектор, можно вычислить центроид и в дальнейшем заменить всю информацию о кластере этим значением (этого достаточно для вычисления большинства необходимых метрик). После фазы 3 мы получаем набор кластеров, который отражает основные характеристики распределяемых данных.&lt;br /&gt;
Однако, всё ещё могут оставаться некоторые неточности, для устранения которых существует фаза 4.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 4&#039;&#039;&#039;. Данная фаза является опциональной и влечёт за собой затраты на дополнительное сканирование данных для корректировки неточностей и дальнейшего улучшения кластеризации. Фаза 4 использует центроиды кластеров, полученные в фазе 3 для как основы и перераспределяет точки входных данных в ближайшие для них основы для получения нового списка кластеров. Фаза 4, если это необходимо пользователю, может быть расширена дополнительными проходами для уверенности в том, что результат приближается к оптимальному.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Последовательную реализацию основных операций алгоритма BIRCH можно продемонстрировать на примере следующего фрагмента кода на языке C++:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot;&amp;gt;&lt;br /&gt;
void CF_Node::insert(const CF_Cluster &amp;amp;entry)&lt;br /&gt;
{&lt;br /&gt;
    //Находим ближайший к новому элементу подкластер в узле&lt;br /&gt;
    СF_Vector_it closest = entry.findClosest(subclusters);&lt;br /&gt;
    //Если узел пустой, добавляем в него новый подкластер&lt;br /&gt;
    if (closest == subclusters.end()) {&lt;br /&gt;
        subclusters.push_back(entry);&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    closest-&amp;gt;add(entry);&lt;br /&gt;
    //Если узел является листьевым, и ближайший подкластер не может вместить&lt;br /&gt;
    //новый элемент, добавляем в узел новый подкластер&lt;br /&gt;
    if (leaf) {&lt;br /&gt;
        if (closest-&amp;gt;D &amp;gt; threshold) {&lt;br /&gt;
            closest-&amp;gt;remove(entry);&lt;br /&gt;
            subclusters.push_back(entry);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else {&lt;br /&gt;
        CF_Node *node = closest-&amp;gt;child;&lt;br /&gt;
        node-&amp;gt;insert(entry);&lt;br /&gt;
        //Если при добавлении нового элемента в дочерний узел тот переполнился,&lt;br /&gt;
        //расщепляем его        &lt;br /&gt;
        if (node-&amp;gt;getSubclusters().size() &amp;gt; bFactor) {&lt;br /&gt;
            CF_Vector newClusters = node-&amp;gt;splitNode();&lt;br /&gt;
            delete node;&lt;br /&gt;
            subclusters.erase(closest);&lt;br /&gt;
            subclusters.insert(subclusters.end(), newClusters.begin(), newClusters.end());&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    //Если узел является корневым и он переполнен, расщепляем его&lt;br /&gt;
    if (root &amp;amp;&amp;amp; subclusters.size() &amp;gt; bFactor) {&lt;br /&gt;
        subclusters = splitNode();&lt;br /&gt;
        leaf = false;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
CF_Vector CF_Node::splitNode()&lt;br /&gt;
{&lt;br /&gt;
    if (subclusters.size() &amp;lt; 2)&lt;br /&gt;
        return (root) ? subclusters : CF_Vector{CF_Cluster(this)};&lt;br /&gt;
    //Находим пару наиболее удаленных друг от друга подкластеров&lt;br /&gt;
    CF_Vector_it pole1, pole2;&lt;br /&gt;
    data_t longestDist = 0.0;&lt;br /&gt;
    for (auto lhs = subclusters.begin(); lhs != subclusters.end() - 1; ++lhs) {&lt;br /&gt;
        for (auto rhs = lhs + 1; rhs != subclusters.end(); ++rhs) {&lt;br /&gt;
            auto distance = getDistance(*lhs, *rhs);&lt;br /&gt;
            if (distance &amp;gt; longestDist) {&lt;br /&gt;
                longestDist = distance;&lt;br /&gt;
                pole1 = lhs;&lt;br /&gt;
                pole2 = rhs;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    //Разделяем множество всех подкластеров узла на две части&lt;br /&gt;
    CF_Vector subclusters1, subclusters2;&lt;br /&gt;
    for (auto it = subclusters.begin(); it != subclusters.end(); ++it) {&lt;br /&gt;
        if (getDistance(*it, *pole1) &amp;lt; getDistance(*it, *pole2))&lt;br /&gt;
            subclusters1.push_back(*it);&lt;br /&gt;
        else&lt;br /&gt;
            subclusters2.push_back(*it);&lt;br /&gt;
    }&lt;br /&gt;
    //Создаем два новых узла&lt;br /&gt;
    CF_Node *node1 = new CF_Node(threshold, bFactor, count, leaf, subclusters1),&lt;br /&gt;
            *node2 = new CF_Node(threshold, bFactor, count, leaf, subclusters2);&lt;br /&gt;
    //Связываем листья&lt;br /&gt;
    if (leaf) {&lt;br /&gt;
        if (prevLeaf) {&lt;br /&gt;
            node1-&amp;gt;setPrevLeaf(prevLeaf);&lt;br /&gt;
            prevLeaf-&amp;gt;setNextLeaf(node1);&lt;br /&gt;
        }&lt;br /&gt;
        if (nextLeaf) {&lt;br /&gt;
            node2-&amp;gt;setNextLeaf(nextLeaf);&lt;br /&gt;
            nextLeaf-&amp;gt;setPrevLeaf(node2);&lt;br /&gt;
        }&lt;br /&gt;
        node1-&amp;gt;setNextLeaf(node2);&lt;br /&gt;
        node2-&amp;gt;setPrevLeaf(node1);&lt;br /&gt;
    }&lt;br /&gt;
    CF_Cluster cluster1(node1), cluster2(node2);&lt;br /&gt;
    return CF_Vector{cluster1, cluster2};&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Для начала проанализируем вычислительную сложность фазы 1.&lt;br /&gt;
Максимальный размер дерева &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt; - ограничение по памяти на размер узла, а &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - общий объем памяти. Для того чтобы вставить элемент, мы должны пройти путь от корня до листа (это около &amp;lt;math&amp;gt;1+log_B\frac{M}{P}&amp;lt;/math&amp;gt; узлов). В каждом узле в поисках &amp;quot;ближайшего&amp;quot; нам необходимо просмотреть B элементов; сложность для каждого элемента пропорциональна размерности &#039;&#039;d&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Поэтому сложность вставки всех входных точек &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В случае, когда необходимо перестроить дерево, предположим, что ES - это размер CF элемента. Существует максимум &amp;lt;math&amp;gt;\frac{M}{ES}&amp;lt;/math&amp;gt; листьевых элементов для вставки, поэтому сложность повторной вставки листьевых элементов &amp;lt;math&amp;gt;O(d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Количество итераций перестройки дерева зависит от пороговой величины. На самом деле, это около &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; (двоичное основание появилось из-за того, что мы не можем провести оценку более чем в 2 раза отличающуюся от текущего размера). &amp;lt;math&amp;gt;N_0&amp;lt;/math&amp;gt; - это число входных точек, загруженных в память с пороговым ограничением &amp;lt;math&amp;gt;T_0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Соответственно, итоговая сложность фазы 1 &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P})+log_2\frac{N}{N_0}*d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Анализ фазы 2 проводится аналогично.&lt;br /&gt;
&lt;br /&gt;
Что касается операций ввода-вывода, то в фазе 1 данные сканируются один раз, а в фазе 2 не сканируются вовсе.&lt;br /&gt;
Некоторое количество вычислений связано с удалением точек из областей с низкой плотностью.&lt;br /&gt;
Если количество доступной для этой операции памяти не больше &#039;&#039;M&#039;&#039; и проведено порядка &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; перестроек дерева, то сложность ввода-вывода для фазы 1 существенно не отличается от сложности чтения из файла. Основываясь рассуждениях выше, сложность фаз 1 и 2 будет линейно увеличиваться с ростом N.&lt;br /&gt;
&lt;br /&gt;
В фазе 3 нет операций ввода-вывода. Её сложность ограничена константой, которая зависит от максимального размера входных данных, и варианта выбранного алгоритма для кластеризации. &lt;br /&gt;
&lt;br /&gt;
Фаза 4 снова сканирует данные и записывает каждую точку в подходящий кластер; время работы пропорционально &amp;lt;math&amp;gt;N*K&amp;lt;/math&amp;gt;.   &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
=== Вычисление расстояния ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2=\frac{N_1*SS_2+N_2*SS_1-2*\vec{LS_1}*\vec{LS_2}}{N_1*N_2}&amp;lt;/math&amp;gt;, где&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF_1=[N_1,\vec{LS_1},SS_1]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF_2=[N_2,\vec{LS_2},SS_2]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:ZgYL51QJsQk.jpg]]&lt;br /&gt;
&amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельно могут быть выполнены следующие шаги алгоритма:&lt;br /&gt;
* Нахождение ближайшего к новому элементу подкластера в узле при выполнении операции вставки. Это возможно за счет того, что расстояние между парами элементов может быть вычислено независимо друг от друга. Сложность &lt;br /&gt;
* Вычисление величин &amp;lt;math&amp;gt;\vec{LS},\vec{X0}, R, D, D_0-D_4&amp;lt;/math&amp;gt;, в процессе чего выполняются операции сложения и скалярного произведения векторов.&lt;br /&gt;
&lt;br /&gt;
Другим способом параллелизации алгоритма может служить создание и заполнение сразу множества кластерных деревьев, между которыми будут распределены входные данные. Множество всех подкластеров листьевых узлов полученных таким образом деревьев может быть подвергнуто глобальной кластеризации с помощью какого-либо из известных параллельных алгоритмов, например, k-средних&amp;lt;ref&amp;gt;[http://people.du.ac.in/~ngupta/Publications/PBIRCH%20A%20Sacalabel%20Paralllel%20Clustering.pdf A Garg, N Gupta PBIRCH: A Scalable Parallel Clustering algorithm for Incremental Data]&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;
* Набор из &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек &amp;lt;math&amp;gt;\{X_i\}, i=1,...,N&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Кластерное дерево с не более чем &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt; узлами.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Достоинства алгоритма ===&lt;br /&gt;
По сравнению с предыдущими методами BIRCH обладает следующими достоинствами:&lt;br /&gt;
&lt;br /&gt;
1. BIRCH является локальным алгоритмом, то есть каждое решение о каждом элементе кластера принимается без повторного сканирования данных или уже существующих кластеров. Используются только метрики, отражающие близость элементов друг к другу.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH использует факт неравномерного распределения данных в пространстве и поэтому не все данные рассматриваются как одинаково важные для построения кластера. Области с большой плотностью обрабатываются как единый кластер. Данные в более разреженных областях могут удаляться (опционально).&lt;br /&gt;
&lt;br /&gt;
3. BIRCH использует всю доступную память для получения наилучших из возможных подкластеров, в то же время минимизируя затраты на операции ввода/вывода. Оптимизация процесса кластеризации достигается за счет использования взвешенно-сбалансированного дерева. При этом время исполнения линейно.&lt;br /&gt;
&lt;br /&gt;
4. BIRCH не требует всего набора данных заранее (при этом просматривает его всего один раз).&lt;br /&gt;
&lt;br /&gt;
=== Недостатки алгоритма ===&lt;br /&gt;
&lt;br /&gt;
1. Алгоритм позволяет работать только с числовыми данными.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH хорошо выделяет только кластеры сферической формы.&lt;br /&gt;
&lt;br /&gt;
3. Существует необходимость в задании пороговых значений.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
В составе пакетов и библиотек:&lt;br /&gt;
* [http://scikit-learn.org/stable/modules/generated/sklearn.cluster.Birch.html scikit-learn]&lt;br /&gt;
* [http://cucis.ece.northwestern.edu/projects/DMS/MineBench.html NU-MineBench]&lt;br /&gt;
Пользовательские реализации:&lt;br /&gt;
* [https://code.google.com/archive/p/jbirch/ JBIRCH]&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Светлана Морозова</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13833</id>
		<title>Участник:Smirnov.maxim/BIRCH</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13833"/>
		<updated>2016-10-26T07:23:55Z</updated>

		<summary type="html">&lt;p&gt;Светлана Морозова: /* Информационный граф */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Авторы: [[Участник:Светлана Морозова|Морозова Светлана]], [[Участник:Smirnov.maxim|Смирнов Максим]].&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Нахождение полезных для анализа закономерностей в больших объёмах данных с недавних пор вызывает значительный интерес. В связи с этим ввелось и стало активно развиваться такое понятие как &#039;&#039;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7 кластеризация]&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Ранние работы и алгоритмы, разработанные в этой области, не уделяли достаточного внимания анализу очень больших наборов данных или минимизации издержек на процессы ввода-вывода.&lt;br /&gt;
Решением этих проблем стал алгоритм, известный как BIRCH.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIRCH&#039;&#039;&#039;&amp;lt;ref&amp;gt;[http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf Нейский И.М. Классификация и сравнение методов кластеризации]&amp;lt;/ref&amp;gt;&amp;lt;ref&amp;gt;[http://www.cs.sfu.ca/CourseCentral/459/han/papers/zhang96.pdf T Zhang, R Ramakrishnan, M Livny. BIRCH: An Efficient Data Clustering Method for Very Large Databases]&amp;lt;/ref&amp;gt; (balanced iterative reducing and clustering using hierarchies)- алгоритм, применяемый в области [https://ru.wikipedia.org/wiki/Data_mining Data mining] и использующий принципы [https://ru.wikipedia.org/wiki/%D0%98%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F иерархической кластеризации].&lt;br /&gt;
&lt;br /&gt;
Если имеется очень большой набор данных, то в пространстве он распределен, как правило, неравномерно. Кластерный анализ определяет места наибольшего и наименьшего скоплений, чтобы таким образом понять всю картину целиком. Кроме того, полученные кластеры визуализируются гораздо нагляднее, чем начальные &amp;quot;сырые&amp;quot; данные.&lt;br /&gt;
Задачей алгоритмов кластеризации является не только простое разбиение данных на кластеры, но и работа в рамках ограниченного объёма доступной памяти (как правило, её объём гораздо меньше, чем размер исходного набора данных) и минимизация времени, требуемого на операции ввода-вывода.&lt;br /&gt;
&lt;br /&gt;
Для наилучшего решения этих проблем BIRCH распределяет входящие данные по кластерам динамически. Для эффективной кластеризации алгоритму требуется всего одно сканирование данных (т.е. с увеличением количества данных сложность увеличивается линейно). А при помощи одной (или более) дополнительных итераций можно и далее улучшать эффективность. BIRCH также является первым алгоритмом, предложенным для эффективного управления &amp;quot;шумами&amp;quot; (данными, которые не вписываются в общее представление модели).&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Теоретическая основа ===&lt;br /&gt;
&lt;br /&gt;
Пусть в кластере имеются &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}, i=1,2,...,N&amp;lt;/math&amp;gt;.&lt;br /&gt;
Тогда &#039;&#039;&#039;центроид&#039;&#039;&#039; &amp;lt;math&amp;gt;{\vec{{X_0}}}&amp;lt;/math&amp;gt;, &#039;&#039;&#039;радиус&#039;&#039;&#039; &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &#039;&#039;&#039;диаметр&#039;&#039;&#039; &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластера определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;{\vec{X_0}}=\frac{\sum_{i=1}^N\vec{X_i}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{\sum_{i=1}^N{(\vec{X_i} - \vec{X_0})}^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{\sum_{i=1}^N\sum_{j=1}^N{(\vec{X_i} - \vec{X_j})}^2}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; - это среднее расстояние от каждой точки до центроида. &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; - это среднее расстояние между парами в кластере. Данные величины являются альтернативными метриками плотности кластера относительно центроида.&lt;br /&gt;
&lt;br /&gt;
Для измерения близости друг к другу двух кластеров вводятся следующие метрики:&lt;br /&gt;
&lt;br /&gt;
пусть даны центроиды двух кластеров &amp;lt;math&amp;gt;\vec{X_{01}}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\vec{X_{02}}&amp;lt;/math&amp;gt;.&lt;br /&gt;
Евклидова метрика &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt; и метрика Манхэттена &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt; между двумя кластерами определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_0 = ((\vec{X_{01}}-\vec{X_{02}})^2)^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_1 = |\vec{X_{01}}-\vec{X_{02}}| = \sum_{i=1}^d |{\vec{X_{01}}}^{(i)}-{\vec{X_{02}}}^{(i)}| &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть имеются два кластера, содержащих соответственно  &amp;lt;math&amp;gt;N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;N_2&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i= 1,2, ...,N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\{\vec{X_j}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j= N_1+1,N_1+2, ...,N_1+N_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Среднее расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &#039;&#039;&#039;среднее внутрикластерное расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &#039;&#039;&#039;дисперсия&#039;&#039;&#039; &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; для двух кластеров определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{\sum_{i=1}^{N_1}\sum_{j=N_1+1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{N_1N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{\sum_{i=1}^{N_1+N_2}\sum_{j=1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_4 = \sum_{k=1}^{N_1+N_2}(\vec{X_k} - \frac{\sum_{i=1}^{N_1+N_2}\vec{X_i}}{N_1+N_2})^2 - \sum_{i=1}^{N_1}(\vec{X_i} - \frac{\sum_{i=1}^{N_1}\vec{X_i}}{N_1})^2 - \sum_{j=N_1+1}^{N_1+N_2}(\vec{X_j} - \frac{\sum_{i=N_1+1}^{N_1+N_2}\vec{X_i}}{N_2})^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Таким образом, величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; относятся к отдельным кластерам, а &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; - к объединению двух кластеров.&lt;br /&gt;
&lt;br /&gt;
=== Кластерный элемент и кластерное дерево ===&lt;br /&gt;
&lt;br /&gt;
В основе концепции алгоритма BIRCH лежат понятия &#039;&#039;&#039;кластерного элемента&#039;&#039;&#039; и &#039;&#039;&#039;кластерного дерева (CF Tree)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====Кластерный элемент ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; Пусть в кластере содержатся  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности  &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;:&amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;i=1,2,...,N&amp;lt;/math&amp;gt;. &lt;br /&gt;
&#039;&#039;&#039;Кластерный элемент (CF)&#039;&#039;&#039; - тройка чисел, характеризующая информацию о кластере: &lt;br /&gt;
&amp;lt;math&amp;gt;CF = (N, \vec{LS}, SS)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - количество элементов входных данных, содержащихся в кластере, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; - линейная сумма входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}\vec{X_i}&amp;lt;/math&amp;gt;), &amp;lt;math&amp;gt;SS&amp;lt;/math&amp;gt; - сумма квадратов входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}{\vec{X_i}}^2&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Теорема&#039;&#039;&#039; Пусть &amp;lt;math&amp;gt;CF_1 = (N_1, \vec{LS_1}, SS_1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;CF_2 = (N_1, \vec{LS_2}, SS_2)&amp;lt;/math&amp;gt; - CF векторы двух непересекающихся кластеров. Тогда при их объединении образуется кластер со следующим CF вектором: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF = CF_1 + CF_2 = (N_1+N_2, \vec{LS_1}+\vec{LS_2}, SS_1+SS_2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Из указанных выше определения и теоремы вытекает тот факт, что при объединении кластеров их CF вектор может вычисляться инкрементно и точно. &lt;br /&gt;
Легко показать, что вычислить величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;, как и обычные метрики, также не составит труда.&lt;br /&gt;
&lt;br /&gt;
Таким образом, в данном случае информацией о кластере является не весь набор точек, а вектор CF. Хранение одного только вектора может показаться неэффективным, но этого вполне достаточно для оперирования всеми необходимыми метриками, на основе которых принимаются решения в алгоритме BIRCH.&lt;br /&gt;
&lt;br /&gt;
==== Кластерное дерево ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; &#039;&#039;&#039;Кластерное дерево (CF Tree)&#039;&#039;&#039; - это взвешенно сбалансированное дерево с двумя параметрами: &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - коэффициент разветвления, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - пороговая величина.&lt;br /&gt;
&lt;br /&gt;
Каждый нелистьевой узел дерева имеет не более чем &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; вхождений узлов следующей формы: &amp;lt;math&amp;gt;[CF_i,child_i]&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i=1,2,...,B&amp;lt;/math&amp;gt;, &#039;&#039;child&#039;&#039; - указатель на i-й дочерний узел, &amp;lt;math&amp;gt;CF_i&amp;lt;/math&amp;gt; - CF вектор соответствующего подкластера.&lt;br /&gt;
&lt;br /&gt;
Каждый листьевой узел имеет ссылку на два соседних узла (&#039;&#039;prev&#039;&#039; и &#039;&#039;next&#039;&#039;) для того, чтобы связать все узлы для эффективного сканирования.&lt;br /&gt;
Все листьевые узлы должны удовлетворять пороговому ограничению &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, т.е. диаметр (радиус) не должен превосходить &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;.&lt;br /&gt;
В процессе вставки новых данных CF дерево строится динамически. Оно использует вставку данных для кластеризации точно также как &amp;lt;math&amp;gt;B+&amp;lt;/math&amp;gt; [https://ru.wikipedia.org/wiki/B%2B-%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE дерево] использует её для поиска.&lt;br /&gt;
CF дерево очень компактно, поскольку каждый листьевой узел - это не просто точка, а подкластер (который объединяет множество точек с учётом ограничения &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Операция вставки в &#039;&#039;&#039;CF&#039;&#039;&#039; дерево ====&lt;br /&gt;
&lt;br /&gt;
Опишем алгоритм вставки элемнта &amp;lt;math&amp;gt;Ent&amp;lt;/math&amp;gt; в CF дерево:&lt;br /&gt;
&lt;br /&gt;
1) &#039;&#039;Определение подходящего листа&#039;&#039;: Начиная с корня, алгоритм рекурсивно спускается по CF дереву, выбирая &#039;&#039;&#039;ближайший&#039;&#039;&#039; дочерний узел в соответствии с выбранной метрикой &amp;lt;math&amp;gt;D0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D4&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &#039;&#039;Преобразование листа&#039;&#039;: Когда алгоритм доходит до листа, он находит ближайшую листьевой элемент, скажем, &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;, а затем проверяет, можно ли добавить &#039;&#039;Ent&#039;&#039; к &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt; без нарушения порогового условия. Если да, то с учётом этого изменяется CF вектор для &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;; если нет, то &#039;&#039;Ent&#039;&#039; становится новым элементом листа. Если в листе для этого достаточно места, то шаг окончен, иначе он должен &amp;quot;расщепиться&amp;quot;. Расщепление узла производится при помощи выбора за основу наиболее удалённой друг от друга пары элементов и перераспределение оставшихся элементов в соответствии с выбранным критерием близости.&lt;br /&gt;
&lt;br /&gt;
3) &#039;&#039;Преобразование пути к листу&#039;&#039;: После вставки &#039;&#039;Ent&#039;&#039; в лист мы должны обновить информацию о CF для каждого нелистьевого элемента на пути к листу. При отсутствии расщепления это означает простое сложение CF векторов для отражения факта добавления &#039;&#039;Ent&#039;&#039;. Расщепление листа же требует вставки нового нелистьевого элемента в родительский узел для задания только что созданного листа. Если у родителя есть место для этого элемента, то необходимо просто преобразовать CF векторы на всех более высоких уровнях. В общем случае, однако, нам также придётся расщепить родительский узел, и так далее до корня. Если расщеплён корень, то высота дерева увеличивается на единицу.&lt;br /&gt;
&lt;br /&gt;
4) &#039;&#039;Улучшение слияния&#039;&#039;: Расщепление вызвано ограничением на размер узла, который не зависит от кластеризационных свойств данных. Если во входящем потоке присутствуют &amp;quot;искажённые&amp;quot; (из областей с низкой плотностью) данные, это может повлиять на качество кластеризации, а также уменьшить эффективность использования памяти. Дополнительный шаг алгоритма помогает решить эти проблемы: предположим, что произошло расщепление листа, и распространение этого процесса остановилось на некотором нелистьевом узле &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt;, то есть &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; может вместить дополнительный элемент, полученный после расщепления. Теперь мы сканируем узел &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; для нахождения двух наиболее близких элементов. Если это не пара, отвечающая расщеплению, мы пытаемся объединить их и поставить в соответствие два дочерних узла. Если количество элементов в дочерних узлах  больше B, мы снова расщепляем результат объединения.&lt;br /&gt;
В процессе повторного расщепления, в случае, если один источник собирает достаточно элементов для того, чтобы полностью заполнить узел, оставшиеся элементы передаются другом источнику. В итоге, если объединённые элементы помещаются в одном узле, в нём освобождается место для ещё одного элемента. Тем самым увеличивается степень использования свободного пространства и откладывается дальнейшее расщепление. В ином случае мы улучшаем распределение элементов в двух ближайших подкластерах.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро алгоритма заключается в многократном выполнении операции вставки нового элемента в дерево, в процессе чего требуется вычисление следующих величин:&lt;br /&gt;
&lt;br /&gt;
* радиуса &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; или диаметра &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластерного элемента. Выполняется при попытке вставить новый элемент в один из подкластеров листьевого узла дерева.&lt;br /&gt;
&lt;br /&gt;
* расстояния между двумя элементами. Выполняется при поиске ближайшего по отношению к новому элементу подкластера в узле дерева по одной из рассмотренных в разд. 1.2.1 метрик &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Зная характеристики кластерных элементов &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;, в результате алгебраических преобразований можно получить следующие упрощенные формулы вычисления необходимых значений:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\vec{X_0} = \frac{\vec{LS}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{SS - 2\vec{X_0}\vec{LS} + N(\vec{X_0})^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{2(N*SS - (\vec{LS})^2)}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{N_1*SS_2 + N_2*SS_1 - 2\vec{LS_1}\vec{LS_2}}{N_1*N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{2((N_1+N_2)(SS_1+SS_2)-(\vec{LS_1}+\vec{LS_2})^2)}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Реализация алгоритма BIRCH состояит из следующих четырёх фаз:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 1&#039;&#039;&#039;. Главной задачей фазы 1 является сканирование всех данных и построение в памяти исходного CF дерева, используя заданное количество памяти. Это дерево стремится отразить информацию о кластеризации данных настолько хорошо, насколько это позволяют ограничения по памяти. При этом плотно распределённые данные группируются в подкластеры, а более разрозненные данные удаляются. После завершения фазы 1 вспомогательные вычисления в дальнейших фазах будут:&lt;br /&gt;
&lt;br /&gt;
1) быстрее, потому что (а) больше не нужны операции ввода-вывода, (b) проблема кластеризации начальных данных упрощается до проблемы кластеризации подкластеров в листьях;&lt;br /&gt;
&lt;br /&gt;
2) точнее, потому что (а) большинство данных с низкой плотностью удалены, (b) оставшиеся данные распределены оптимально (в соответствии с доступным количеством памяти);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 2&#039;&#039;&#039;. Данная фаза является опциональной. Известно, что существующие методы глобальной кластеризации, используемые в рамках фазы 3, имеют различные диапазоны входных значений, при которых их реализация наиболее эффективна. Поэтому потенциально существует пробел между размером фазы 1 и входными значениями фазы 3. И фаза 2 как раз является недостающим связующим звеном: так же как и фаза 1, она сканирует листьевые элементы начального CF дерева для того, чтобы построить меньшее дерево, удаляя ещё больше элементов с низкой плотностью и группируя переполненные подкластеры в большие кластеры.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 3&#039;&#039;&#039;. В данной фазе для листьевых элементов применяется (любой подходящий) алгоритм глобальной кластеризации. Существующие алгоритмы кластеризации наборов точек могут также работать с наборами подкластеров, каждый из которых представлен своим CF вектором. Зная CF вектор, можно вычислить центроид и в дальнейшем заменить всю информацию о кластере этим значением (этого достаточно для вычисления большинства необходимых метрик). После фазы 3 мы получаем набор кластеров, который отражает основные характеристики распределяемых данных.&lt;br /&gt;
Однако, всё ещё могут оставаться некоторые неточности, для устранения которых существует фаза 4.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 4&#039;&#039;&#039;. Данная фаза является опциональной и влечёт за собой затраты на дополнительное сканирование данных для корректировки неточностей и дальнейшего улучшения кластеризации. Фаза 4 использует центроиды кластеров, полученные в фазе 3 для как основы и перераспределяет точки входных данных в ближайшие для них основы для получения нового списка кластеров. Фаза 4, если это необходимо пользователю, может быть расширена дополнительными проходами для уверенности в том, что результат приближается к оптимальному.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
Последовательную реализацию основных операций алгоритма BIRCH можно продемонстрировать на примере следующего фрагмента кода на языке C++:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c++&amp;quot;&amp;gt;&lt;br /&gt;
void CF_Node::insert(const CF_Cluster &amp;amp;entry)&lt;br /&gt;
{&lt;br /&gt;
    //Находим ближайший к новому элементу подкластер в узле&lt;br /&gt;
    СF_Vector_it closest = entry.findClosest(subclusters);&lt;br /&gt;
    //Если узел пустой, добавляем в него новый подкластер&lt;br /&gt;
    if (closest == subclusters.end()) {&lt;br /&gt;
        subclusters.push_back(entry);&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    closest-&amp;gt;add(entry);&lt;br /&gt;
    //Если узел является листьевым, и ближайший подкластер не может вместить&lt;br /&gt;
    //новый элемент, добавляем в узел новый подкластер&lt;br /&gt;
    if (leaf) {&lt;br /&gt;
        if (closest-&amp;gt;D &amp;gt; threshold) {&lt;br /&gt;
            closest-&amp;gt;remove(entry);&lt;br /&gt;
            subclusters.push_back(entry);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    else {&lt;br /&gt;
        CF_Node *node = closest-&amp;gt;child;&lt;br /&gt;
        node-&amp;gt;insert(entry);&lt;br /&gt;
        //Если при добавлении нового элемента в дочерний узел тот переполнился,&lt;br /&gt;
        //расщепляем его        &lt;br /&gt;
        if (node-&amp;gt;getSubclusters().size() &amp;gt; bFactor) {&lt;br /&gt;
            CF_Vector newClusters = node-&amp;gt;splitNode();&lt;br /&gt;
            delete node;&lt;br /&gt;
            subclusters.erase(closest);&lt;br /&gt;
            subclusters.insert(subclusters.end(), newClusters.begin(), newClusters.end());&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    //Если узел является корневым и он переполнен, расщепляем его&lt;br /&gt;
    if (root &amp;amp;&amp;amp; subclusters.size() &amp;gt; bFactor) {&lt;br /&gt;
        subclusters = splitNode();&lt;br /&gt;
        leaf = false;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
CF_Vector CF_Node::splitNode()&lt;br /&gt;
{&lt;br /&gt;
    if (subclusters.size() &amp;lt; 2)&lt;br /&gt;
        return (root) ? subclusters : CF_Vector{CF_Cluster(this)};&lt;br /&gt;
    //Находим пару наиболее удаленных друг от друга подкластеров&lt;br /&gt;
    CF_Vector_it pole1, pole2;&lt;br /&gt;
    data_t longestDist = 0.0;&lt;br /&gt;
    for (auto lhs = subclusters.begin(); lhs != subclusters.end() - 1; ++lhs) {&lt;br /&gt;
        for (auto rhs = lhs + 1; rhs != subclusters.end(); ++rhs) {&lt;br /&gt;
            auto distance = getDistance(*lhs, *rhs);&lt;br /&gt;
            if (distance &amp;gt; longestDist) {&lt;br /&gt;
                longestDist = distance;&lt;br /&gt;
                pole1 = lhs;&lt;br /&gt;
                pole2 = rhs;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    //Разделяем множество всех подкластеров узла на две части&lt;br /&gt;
    CF_Vector subclusters1, subclusters2;&lt;br /&gt;
    for (auto it = subclusters.begin(); it != subclusters.end(); ++it) {&lt;br /&gt;
        if (getDistance(*it, *pole1) &amp;lt; getDistance(*it, *pole2))&lt;br /&gt;
            subclusters1.push_back(*it);&lt;br /&gt;
        else&lt;br /&gt;
            subclusters2.push_back(*it);&lt;br /&gt;
    }&lt;br /&gt;
    //Создаем два новых узла&lt;br /&gt;
    CF_Node *node1 = new CF_Node(threshold, bFactor, count, leaf, subclusters1),&lt;br /&gt;
            *node2 = new CF_Node(threshold, bFactor, count, leaf, subclusters2);&lt;br /&gt;
    //Связываем листья&lt;br /&gt;
    if (leaf) {&lt;br /&gt;
        if (prevLeaf) {&lt;br /&gt;
            node1-&amp;gt;setPrevLeaf(prevLeaf);&lt;br /&gt;
            prevLeaf-&amp;gt;setNextLeaf(node1);&lt;br /&gt;
        }&lt;br /&gt;
        if (nextLeaf) {&lt;br /&gt;
            node2-&amp;gt;setNextLeaf(nextLeaf);&lt;br /&gt;
            nextLeaf-&amp;gt;setPrevLeaf(node2);&lt;br /&gt;
        }&lt;br /&gt;
        node1-&amp;gt;setNextLeaf(node2);&lt;br /&gt;
        node2-&amp;gt;setPrevLeaf(node1);&lt;br /&gt;
    }&lt;br /&gt;
    CF_Cluster cluster1(node1), cluster2(node2);&lt;br /&gt;
    return CF_Vector{cluster1, cluster2};&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Для начала проанализируем вычислительную сложность фазы 1.&lt;br /&gt;
Максимальный размер дерева &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;P&amp;lt;/math&amp;gt; - ограничение по памяти на размер узла, а &amp;lt;math&amp;gt;M&amp;lt;/math&amp;gt; - общий объем памяти. Для того чтобы вставить элемент, мы должны пройти путь от корня до листа (это около &amp;lt;math&amp;gt;1+log_B\frac{M}{P}&amp;lt;/math&amp;gt; узлов). В каждом узле в поисках &amp;quot;ближайшего&amp;quot; нам необходимо просмотреть B элементов; сложность для каждого элемента пропорциональна размерности &#039;&#039;d&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Поэтому сложность вставки всех входных точек &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В случае, когда необходимо перестроить дерево, предположим, что ES - это размер CF элемента. Существует максимум &amp;lt;math&amp;gt;\frac{M}{ES}&amp;lt;/math&amp;gt; листьевых элементов для вставки, поэтому сложность повторной вставки листьевых элементов &amp;lt;math&amp;gt;O(d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Количество итераций перестройки дерева зависит от пороговой величины. На самом деле, это около &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; (двоичное основание появилось из-за того, что мы не можем провести оценку более чем в 2 раза отличающуюся от текущего размера). &amp;lt;math&amp;gt;N_0&amp;lt;/math&amp;gt; - это число входных точек, загруженных в память с пороговым ограничением &amp;lt;math&amp;gt;T_0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Соответственно, итоговая сложность фазы 1 &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P})+log_2\frac{N}{N_0}*d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Анализ фазы 2 проводится аналогично.&lt;br /&gt;
&lt;br /&gt;
Что касается операций ввода-вывода, то в фазе 1 данные сканируются один раз, а в фазе 2 не сканируются вовсе.&lt;br /&gt;
Некоторое количество вычислений связано с удалением точек из областей с низкой плотностью.&lt;br /&gt;
Если количество доступной для этой операции памяти не больше &#039;&#039;M&#039;&#039; и проведено порядка &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; перестроек дерева, то сложность ввода-вывода для фазы 1 существенно не отличается от сложности чтения из файла. Основываясь рассуждениях выше, сложность фаз 1 и 2 будет линейно увеличиваться с ростом N.&lt;br /&gt;
&lt;br /&gt;
В фазе 3 нет операций ввода-вывода. Её сложность ограничена константой, которая зависит от максимального размера входных данных, и варианта выбранного алгоритма для кластеризации. &lt;br /&gt;
&lt;br /&gt;
Фаза 4 снова сканирует данные и записывает каждую точку в подходящий кластер; время работы пропорционально &amp;lt;math&amp;gt;N*K&amp;lt;/math&amp;gt;.   &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
=== Вычисление расстояния ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2=\frac{N_1*SS_2+N_2*SS_1-2*\vec{LS_1}*\vec{LS_2}}{N_1*N_2}&amp;lt;/math&amp;gt;, где&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF_1=[N_1,\vec{LS_1},SS_1]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF_2=[N_2,\vec{LS_2},SS_2]&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
Параллельно могут быть выполнены следующие шаги алгоритма:&lt;br /&gt;
* Нахождение ближайшего к новому элементу подкластера в узле при выполнении операции вставки. Это возможно за счет того, что расстояние между парами элементов может быть вычислено независимо друг от друга. Сложность &lt;br /&gt;
* Вычисление величин &amp;lt;math&amp;gt;\vec{LS},\vec{X0}, R, D, D_0-D_4&amp;lt;/math&amp;gt;, в процессе чего выполняются операции сложения и скалярного произведения векторов.&lt;br /&gt;
&lt;br /&gt;
Другим способом параллелизации алгоритма может служить создание и заполнение сразу множества кластерных деревьев, между которыми будут распределены входные данные. Множество всех подкластеров листьевых узлов полученных таким образом деревьев может быть подвергнуто глобальной кластеризации с помощью какого-либо из известных параллельных алгоритмов, например, k-средних&amp;lt;ref&amp;gt;[http://people.du.ac.in/~ngupta/Publications/PBIRCH%20A%20Sacalabel%20Paralllel%20Clustering.pdf A Garg, N Gupta PBIRCH: A Scalable Parallel Clustering algorithm for Incremental Data]&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;
* Набор из &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек &amp;lt;math&amp;gt;\{X_i\}, i=1,...,N&amp;lt;/math&amp;gt; размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Кластерное дерево с не более чем &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt; узлами.&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Достоинства алгоритма ===&lt;br /&gt;
По сравнению с предыдущими методами BIRCH обладает следующими достоинствами:&lt;br /&gt;
&lt;br /&gt;
1. BIRCH является локальным алгоритмом, то есть каждое решение о каждом элементе кластера принимается без повторного сканирования данных или уже существующих кластеров. Используются только метрики, отражающие близость элементов друг к другу.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH использует факт неравномерного распределения данных в пространстве и поэтому не все данные рассматриваются как одинаково важные для построения кластера. Области с большой плотностью обрабатываются как единый кластер. Данные в более разреженных областях могут удаляться (опционально).&lt;br /&gt;
&lt;br /&gt;
3. BIRCH использует всю доступную память для получения наилучших из возможных подкластеров, в то же время минимизируя затраты на операции ввода/вывода. Оптимизация процесса кластеризации достигается за счет использования взвешенно-сбалансированного дерева. При этом время исполнения линейно.&lt;br /&gt;
&lt;br /&gt;
4. BIRCH не требует всего набора данных заранее (при этом просматривает его всего один раз).&lt;br /&gt;
&lt;br /&gt;
=== Недостатки алгоритма ===&lt;br /&gt;
&lt;br /&gt;
1. Алгоритм позволяет работать только с числовыми данными.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH хорошо выделяет только кластеры сферической формы.&lt;br /&gt;
&lt;br /&gt;
3. Существует необходимость в задании пороговых значений.&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
В составе пакетов и библиотек:&lt;br /&gt;
* [http://scikit-learn.org/stable/modules/generated/sklearn.cluster.Birch.html scikit-learn]&lt;br /&gt;
* [http://cucis.ece.northwestern.edu/projects/DMS/MineBench.html NU-MineBench]&lt;br /&gt;
Пользовательские реализации:&lt;br /&gt;
* [https://code.google.com/archive/p/jbirch/ JBIRCH]&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;/div&gt;</summary>
		<author><name>Светлана Морозова</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13537</id>
		<title>Участник:Smirnov.maxim/BIRCH</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13537"/>
		<updated>2016-10-23T16:50:04Z</updated>

		<summary type="html">&lt;p&gt;Светлана Морозова: /* Литература */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Нахождение полезных для анализа закономерностей в больших объёмах данных с недавних пор вызывает значительный интерес. В связи с этим ввелось и стало активно развиваться такое понятие как &#039;&#039;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7 кластеризация]&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Ранние работы и алгоритмы, разработанные в этой области, не уделяли достаточного внимания анализу очень больших наборов данных или минимизации издержек на процессы ввода-вывода.&lt;br /&gt;
Решением этих проблем стал алгоритм, известный как BIRCH.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIRCH&#039;&#039;&#039; (balanced iterative reducing and clustering using hierarchies)- алгоритм, применяемый в области [https://ru.wikipedia.org/wiki/Data_mining Data mining] и использующий принципы [https://ru.wikipedia.org/wiki/%D0%98%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F иерархической кластеризации].&lt;br /&gt;
&lt;br /&gt;
Если имеется очень большой набор данных, то в пространстве он распределен, как правило, неравномерно. Кластерный анализ определяет места наибольшего и наименьшего скоплений, чтобы таким образом понять всю картину целиком. Кроме того, полученные кластеры визуализируются гораздо нагляднее, чем начальные &amp;quot;сырые&amp;quot; данные.&lt;br /&gt;
Задачей алгоритмов кластеризации является не только простое разбиение данных на кластеры, но и работа в рамках ограниченного объёма доступной памяти (как правило, её объём гораздо меньше, чем размер исходного набора данных) и минимизация времени, требуемого на операции ввода-вывода.&lt;br /&gt;
&lt;br /&gt;
Для наилучшего решения этих проблем BIRCH распределяет входящие данные по кластерам динамически. Для эффективной кластеризации алгоритму требуется всего одно сканирование данных (т.е. с увеличением количества данных сложность увеличивается линейно). А при помощи одной (или более) дополнительных итераций можно и далее улучшать эффективность. BIRCH также является первым алгоритмом, предложенным для эффективного управления &amp;quot;шумами&amp;quot; (данными, которые не вписываются в общее представление модели).&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Теоретическая основа ===&lt;br /&gt;
&lt;br /&gt;
Пусть в кластере имеются &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}, i=1,2,...,N&amp;lt;/math&amp;gt;.&lt;br /&gt;
Тогда &#039;&#039;&#039;центроид&#039;&#039;&#039; &amp;lt;math&amp;gt;{\vec{{X_0}}}&amp;lt;/math&amp;gt;, &#039;&#039;&#039;радиус&#039;&#039;&#039; &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &#039;&#039;&#039;диаметр&#039;&#039;&#039; &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластера определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;{\vec{X_0}}=\frac{\sum_{i=1}^N\vec{X_i}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{\sum_{i=1}^N{(\vec{X_i} - \vec{X_0})}^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{\sum_{i=1}^N\sum_{j=1}^N{(\vec{X_i} - \vec{X_j})}^2}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; - это среднее расстояние от каждой точки до центроида. &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; - это среднее расстояние между парами в кластере. Данные величины являются альтернативными метриками плотности кластера относительно центроида.&lt;br /&gt;
&lt;br /&gt;
Для измерения близости друг к другу двух кластеров вводятся следующие метрики:&lt;br /&gt;
&lt;br /&gt;
пусть даны центроиды двух кластеров &amp;lt;math&amp;gt;\vec{X_{01}}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\vec{X_{02}}&amp;lt;/math&amp;gt;.&lt;br /&gt;
Евклидова метрика &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt; и метрика Манхэттена &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt; между двумя кластерами определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_0 = ((\vec{X_{01}}-\vec{X_{02}})^2)^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_1 = |\vec{X_{01}}-\vec{X_{02}}| = \sum_{i=1}^d |{\vec{X_{01}}}^{(i)}-{\vec{X_{02}}}^{(i)}| &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть имеются два кластера, содержащих соответственно  &amp;lt;math&amp;gt;N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;N_2&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i= 1,2, ...,N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\{\vec{X_j}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j= N_1+1,N_1+2, ...,N_1+N_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Среднее расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &#039;&#039;&#039;среднее внутрикластерное расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &#039;&#039;&#039;дисперсия&#039;&#039;&#039; &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; для двух кластеров определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{\sum_{i=1}^{N_1}\sum_{j=N_1+1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{N_1N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{\sum_{i=1}^{N_1+N_2}\sum_{j=1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_4 = \sum_{k=1}^{N_1+N_2}(\vec{X_k} - \frac{\sum_{i=1}^{N_1+N_2}\vec{X_i}}{N_1+N_2})^2 - \sum_{i=1}^{N_1}(\vec{X_i} - \frac{\sum_{i=1}^{N_1}\vec{X_i}}{N_1})^2 - \sum_{j=N_1+1}^{N_1+N_2}(\vec{X_j} - \frac{\sum_{i=N_1+1}^{N_1+N_2}\vec{X_i}}{N_2})^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Таким образом, величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; относятся к отдельным кластерам, а &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; - к объединению двух кластеров.&lt;br /&gt;
&lt;br /&gt;
=== Кластерный элемент и кластерное дерево ===&lt;br /&gt;
&lt;br /&gt;
В основе концепции алгоритма BIRCH лежат понятия &#039;&#039;&#039;кластерного элемента&#039;&#039;&#039; и &#039;&#039;&#039;кластерного дерева (CF Tree)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====Кластерный элемент ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; Пусть в кластере содержатся  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности  &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;:&amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;i=1,2,...,N&amp;lt;/math&amp;gt;. &lt;br /&gt;
&#039;&#039;&#039;Кластерный элемент (CF)&#039;&#039;&#039; - тройка чисел, характеризующая информацию о кластере: &lt;br /&gt;
&amp;lt;math&amp;gt;CF = (N, \vec{LS}, SS)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - количество элементов входных данных, содержащихся в кластере, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; - линейная сумма входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}\vec{X_i}&amp;lt;/math&amp;gt;), &amp;lt;math&amp;gt;SS&amp;lt;/math&amp;gt; - сумма квадратов входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}{\vec{X_i}}^2&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Теорема&#039;&#039;&#039; Пусть &amp;lt;math&amp;gt;CF_1 = (N_1, \vec{LS_1}, SS_1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;CF_2 = (N_1, \vec{LS_2}, SS_2)&amp;lt;/math&amp;gt; - CF векторы двух непересекающихся кластеров. Тогда при их объединении образуется кластер со следующим CF вектором: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF = CF_1 + CF_2 = (N_1+N_2, \vec{LS_1}+\vec{LS_2}, SS_1+SS_2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Из указанных выше определения и теоремы вытекает тот факт, что при объединении кластеров их CF вектор может вычисляться инкрементно и точно. &lt;br /&gt;
Легко показать, что вычислить величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;, как и обычные метрики, также не составит труда.&lt;br /&gt;
&lt;br /&gt;
Таким образом, в данном случае информацией о кластере является не весь набор точек, а вектор CF. Хранение одного только вектора может показаться неэффективным, но этого вполне достаточно для оперирования всеми необходимыми метриками, на основе которых принимаются решения в алгоритме BIRCH.&lt;br /&gt;
&lt;br /&gt;
==== Кластерное дерево ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; &#039;&#039;&#039;Кластерное дерево (CF Tree)&#039;&#039;&#039; - это взвешенно сбалансированное дерево с двумя параметрами: &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - коэффициент разветвления, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - пороговая величина. Каждый нелистьевой узел дерева имеет не более чем &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; вхождений узлов следующей формы: &amp;lt;math&amp;gt;[CF_i,child_i]&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i=1,2,...,B&amp;lt;/math&amp;gt;, &#039;&#039;child&#039;&#039; - указатель на i-й дочерний узел, &amp;lt;math&amp;gt;CF_i&amp;lt;/math&amp;gt; - CF вектор соответствующего подкластера.&lt;br /&gt;
&lt;br /&gt;
Каждый листьевой узел имеет ссылку на два соседних узла (&#039;&#039;prev&#039;&#039; и &#039;&#039;next&#039;&#039;) для того, чтобы связать все узлы для эффективного сканирования.&lt;br /&gt;
Все листьевые узлы должны удовлетворять пороговому ограничению &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, т.е. диаметр (радиус) не должен превосходить &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;.&lt;br /&gt;
В процессе вставки новых данных CF дерево строится динамически. Оно использует вставку данных для кластеризации точно также как &amp;lt;math&amp;gt;B+&amp;lt;/math&amp;gt; [https://ru.wikipedia.org/wiki/B%2B-%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE дерево] использует её для поиска.&lt;br /&gt;
CF дерево очень компактно, поскольку каждый листьевой узел - это не просто точка, а подкластер (который объединяет множество точек с учётом ограничения &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Операция вставки в &#039;&#039;&#039;CF&#039;&#039;&#039; дерево ====&lt;br /&gt;
&lt;br /&gt;
Опишем алгоритм вставки элемнта &amp;lt;math&amp;gt;Ent&amp;lt;/math&amp;gt; в CF дерево:&lt;br /&gt;
&lt;br /&gt;
1) &#039;&#039;Определение подходящего листа&#039;&#039;: Начиная с корня, алгоритм рекурсивно спускается по CF дереву, выбирая &#039;&#039;&#039;ближайший&#039;&#039;&#039; дочерний узел в соответствии с выбранной метрикой &amp;lt;math&amp;gt;D0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D4&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &#039;&#039;Преобразование листа&#039;&#039;: Когда алгоритм доходит до листа, он находит ближайшую листьевой элемент, скажем, &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;, а затем проверяет, можно ли добавить &#039;&#039;Ent&#039;&#039; к &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt; без нарушения порогового условия. Если да, то с учётом этого изменяется CF вектор для &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;; если нет, то &#039;&#039;Ent&#039;&#039; становится новым элементом листа. Если в листе для этого достаточно места, то шаг окончен, иначе он должен &amp;quot;расщепиться&amp;quot;. Расщепление узла производится при помощи выбора за основу наиболее удалённой друг от друга пары элементов и перераспределение оставшихся элементов в соответствии с выбранным критерием близости.&lt;br /&gt;
&lt;br /&gt;
3) &#039;&#039;Преобразование пути к листу&#039;&#039;: После вставки &#039;&#039;Ent&#039;&#039; в лист мы должны обновить информацию о CF для каждого нелистьевого элемента на пути к листу. При отсутствии расщепления это означает простое сложение CF векторов для отражения факта добавления &#039;&#039;Ent&#039;&#039;. Расщепление листа же требует вставки нового нелистьевого элемента в родительский узел для задания только что созданного листа. Если у родителя есть место для этого элемента, то необходимо просто преобразовать CF векторы на всех более высоких уровнях. В общем случае, однако, нам также придётся расщепить родительский узел, и так далее до корня. Если расщеплён корень, то высота дерева увеличивается на единицу.&lt;br /&gt;
&lt;br /&gt;
4) &#039;&#039;Улучшение слияния&#039;&#039;: Расщепление вызвано ограничением на размер узла, который не зависит от кластеризационных свойств данных. Если во входящем потоке присутствуют &amp;quot;искажённые&amp;quot; (из областей с низкой плотностью) данные, это может повлиять на качество кластеризации, а также уменьшить эффективность использования памяти. Дополнительный шаг алгоритма помогает решить эти проблемы: предположим, что произошло расщепление листа, и распространение этого процесса остановилось на некотором нелистьевом узле &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt;, то есть &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; может вместить дополнительный элемент, полученный после расщепления. Теперь мы сканируем узел &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; для нахождения двух наиболее близких элементов. Если это не пара, отвечающая расщеплению, мы пытаемся объединить их и поставить в соответствие два дочерних узла. Если количество элементов в дочерних узлах  больше B, мы снова расщепляем результат объединения.&lt;br /&gt;
В процессе повторного расщепления, в случае, если один источник собирает достаточно элементов для того, чтобы полностью заполнить узел, оставшиеся элементы передаются другом источнику. В итоге, если объединённые элементы помещаются в одном узле, в нём освобождается место для ещё одного элемента. Тем самым увеличивается степень использования свободного пространства и откладывается дальнейшее расщепление. В ином случае мы улучшаем распределение элементов в двух ближайших подкластерах.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро алгоритма заключается в многократном выполнении операции вставки нового элемента в дерево, в процессе чего требуется вычисление следующих величин:&lt;br /&gt;
&lt;br /&gt;
* радиуса &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; или диаметра &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластерного элемента. Выполняется при попытке вставить новый элемент в один из подкластеров листьевого узла дерева.&lt;br /&gt;
&lt;br /&gt;
* расстояния между двумя элементами. Выполняется при поиске ближайшего по отношению к новому элементу подкластера в узле дерева по одной из рассмотренных в разд. 1.2.1 метрик &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Зная характеристики кластерных элементов &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;, в результате алгебраических преобразований можно получить следующие упрощенные формулы вычисления необходимых значений:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\vec{X_0} = \frac{\vec{LS}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{SS - 2\vec{X_0}\vec{LS} + N(\vec{X_0})^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{2(N*SS - (\vec{LS})^2)}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{N_1*SS_2 + N_2*SS_1 - 2\vec{LS_1}\vec{LS_2}}{N_1*N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{2((N_1+N_2)(SS_1+SS_2)-(\vec{LS_1}+\vec{LS_2})^2)}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Реализация алгоритма BIRCH состояит из следующих четырёх фаз:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 1&#039;&#039;&#039;. Главной задачей фазы 1 является сканирование всех данных и построение в памяти исходного CF дерева, используя заданное количество памяти. Это дерево стремится отразить информацию о кластеризации данных настолько хорошо, насколько это позволяют ограничения по памяти. При этом плотно распределённые данные группируются в подкластеры, а более разрозненные данные удаляются. После завершения фазы 1 вспомогательные вычисления в дальнейших фазах будут:&lt;br /&gt;
&lt;br /&gt;
1) быстрее, потому что (а) больше не нужны операции ввода-вывода, (b) проблема кластеризации начальных данных упрощается до проблемы кластеризации подкластеров в листьях;&lt;br /&gt;
&lt;br /&gt;
2) точнее, потому что (а) большинство данных с низкой плотностью удалены, (b) оставшиеся данные распределены оптимально (в соответствии с доступным количеством памяти);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 2&#039;&#039;&#039;. Данная фаза является опциональной. Известно, что существующие методы глобальной кластеризации, используемые в рамках фазы 3, имеют различные диапазоны входных значений, при которых их реализация наиболее эффективна. Поэтому потенциально существует пробел между размером фазы 1 и входными значениями фазы 3. И фаза 2 как раз является недостающим связующим звеном: так же как и фаза 1, она сканирует листьевые элементы начального CF дерева для того, чтобы построить меньшее дерево, удаляя ещё больше элементов с низкой плотностью и группируя переполненные подкластеры в большие кластеры.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 3&#039;&#039;&#039;. В данной фазе для листьевых элементов применяется (любой подходящий) алгоритм глобальной кластеризации. Существующие алгоритмы кластеризации наборов точек могут также работать с наборами подкластеров, каждый из которых представлен своим CF вектором. Зная CF вектор, можно вычислить центроид и в дальнейшем заменить всю информацию о кластере этим значением (этого достаточно для вычисления большинства необходимых метрик). После фазы 3 мы получаем набор кластеров, который отражает основные характеристики распределяемых данных.&lt;br /&gt;
Однако, всё ещё могут оставаться некоторые неточности, для устранения которых существует фаза 4.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 4&#039;&#039;&#039;. Данная фаза является опциональной и влечёт за собой затраты на дополнительное сканирование данных для корректировки неточностей и дальнейшего улучшения кластеризации. Фаза 4 использует центроиды кластеров, полученные в фазе 3 для как основы и перераспределяет точки входных данных в ближайшие для них основы для получения нового списка кластеров. Фаза 4, если это необходимо пользователю, может быть расширена дополнительными проходами для уверенности в том, что результат приближается к оптимальному.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Для начала проанализируем вычислительную сложность фазы 1.&lt;br /&gt;
Максимальный размер дерева &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt;. Для того чтобы вставить элемент, мы должны пройти путь от корня до листа (это около &amp;lt;math&amp;gt;1+log_B\frac{M}{P}&amp;lt;/math&amp;gt; узлов). В каждом узле в поисках &amp;quot;ближайшего&amp;quot; нам необходимо просмотреть B элементов; сложность для каждого элемента пропорциональна размерности &#039;&#039;d&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Поэтому сложность вставки всех входных точек &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В случае, когда необходимо перестроить дерево, предположим, что ES - это размер CF элемента. Существует максимум &amp;lt;math&amp;gt;\frac{M}{ES}&amp;lt;/math&amp;gt; листьевых элементов для вставки, поэтому сложность повторной вставки листьевых элементов &amp;lt;math&amp;gt;O(d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Количество итераций перестройки дерева зависит от пороговой величины. На самом деле, это около &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; (двоичное основание появилось из-за того, что мы не можем провести оценку более чем в 2 раза отличающуюся от текущего размера). &amp;lt;math&amp;gt;N_0&amp;lt;/math&amp;gt; - это число входных точек, загруженных в память с пороговым ограничением &amp;lt;math&amp;gt;T_0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Соответственно, итоговая сложность фазы 1 &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P})+log_2\frac{N}{N_0}*d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Анализ фазы 2 проводится аналогично.&lt;br /&gt;
&lt;br /&gt;
Что касается операций ввода-вывода, то в фазе 1 данные сканируются один раз, а в фазе 2 не сканируются вовсе.&lt;br /&gt;
Некоторое количество вычислений связано с удалением точек из областей с низкой плотностью.&lt;br /&gt;
Если количество доступной для этой операции памяти не больше &#039;&#039;M&#039;&#039; и проведено порядка &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; перестроек дерева, то сложность ввода-вывода для фазы 1 существенно не отличается от сложности чтения из файла. Основываясь рассуждениях выше, сложность фаз 1 и 2 будет линейно увеличиваться с ростом N.&lt;br /&gt;
&lt;br /&gt;
В фазе 3 нет операций ввода-вывода. Её сложность ограничена константой, которая зависит от максимального размера входных данных, и варианта выбранного алгоритма для кластеризации. &lt;br /&gt;
&lt;br /&gt;
Фаза 4 снова сканирует данные и записывает каждую точку в подходящий кластер; время работы пропорционально &amp;lt;math&amp;gt;N*K&amp;lt;/math&amp;gt;.   &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Достоинства алгоритма ===&lt;br /&gt;
По сравнению с предыдущими методами BIRCH обладает следующими достоинствами:&lt;br /&gt;
&lt;br /&gt;
1. BIRCH является локальным алгоритмом, то есть каждое решение о каждом элементе кластера принимается без повторного сканирования данных или уже существующих кластеров. Используются только метрики, отражающие близость элементов друг к другу.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH использует факт неравномерного распределения данных в пространстве и поэтому не все данные рассматриваются как одинаково важные для построения кластера. Области с большой плотностью обрабатываются как единый кластер. Данные в более разреженных областях могут удаляться (опционально).&lt;br /&gt;
&lt;br /&gt;
3. BIRCH использует всю доступную память для получения наилучших из возможных подкластеров, в то же время минимизируя затраты на операции ввода/вывода. Оптимизация процесса кластеризации достигается за счет использования взвешенно-сбалансированного дерева. При этом время исполнения линейно.&lt;br /&gt;
&lt;br /&gt;
4. BIRCH не требует всего набора данных заранее (при этом просматривает его всего один раз).&lt;br /&gt;
&lt;br /&gt;
=== Недостатки алгоритма ===&lt;br /&gt;
&lt;br /&gt;
1. Алгоритм позволяет работать только с числовыми данными.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH хорошо выделяет только кластеры сферической формы.&lt;br /&gt;
&lt;br /&gt;
3. Существует необходимость в задании пороговых значений.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* [https://code.google.com/archive/p/jbirch/ Java]&lt;br /&gt;
* [http://scikit-learn.org/stable/modules/generated/sklearn.cluster.Birch.html Python]&lt;br /&gt;
* [http://cucis.ece.northwestern.edu/projects/DMS/MineBench.html#description]&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&lt;br /&gt;
* [http://www.cs.sfu.ca/CourseCentral/459/han/papers/zhang96.pdf T Zhang, R Ramakrishnan, M Livny. BIRCH: An Efficient Data Clustering Method for Very Large Databases]&lt;br /&gt;
* [http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf Нейский И.М. Классификация и сравнение методов кластеризации]&lt;br /&gt;
* [http://people.du.ac.in/~ngupta/Publications/PBIRCH%20A%20Sacalabel%20Paralllel%20Clustering.pdf A Garg, N Gupta PBIRCH: A Scalable Parallel Clustering algorithm for Incremental Data]&lt;/div&gt;</summary>
		<author><name>Светлана Морозова</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13536</id>
		<title>Участник:Smirnov.maxim/BIRCH</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13536"/>
		<updated>2016-10-23T16:48:47Z</updated>

		<summary type="html">&lt;p&gt;Светлана Морозова: /* Литература */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Нахождение полезных для анализа закономерностей в больших объёмах данных с недавних пор вызывает значительный интерес. В связи с этим ввелось и стало активно развиваться такое понятие как &#039;&#039;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7 кластеризация]&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Ранние работы и алгоритмы, разработанные в этой области, не уделяли достаточного внимания анализу очень больших наборов данных или минимизации издержек на процессы ввода-вывода.&lt;br /&gt;
Решением этих проблем стал алгоритм, известный как BIRCH.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIRCH&#039;&#039;&#039; (balanced iterative reducing and clustering using hierarchies)- алгоритм, применяемый в области [https://ru.wikipedia.org/wiki/Data_mining Data mining] и использующий принципы [https://ru.wikipedia.org/wiki/%D0%98%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F иерархической кластеризации].&lt;br /&gt;
&lt;br /&gt;
Если имеется очень большой набор данных, то в пространстве он распределен, как правило, неравномерно. Кластерный анализ определяет места наибольшего и наименьшего скоплений, чтобы таким образом понять всю картину целиком. Кроме того, полученные кластеры визуализируются гораздо нагляднее, чем начальные &amp;quot;сырые&amp;quot; данные.&lt;br /&gt;
Задачей алгоритмов кластеризации является не только простое разбиение данных на кластеры, но и работа в рамках ограниченного объёма доступной памяти (как правило, её объём гораздо меньше, чем размер исходного набора данных) и минимизация времени, требуемого на операции ввода-вывода.&lt;br /&gt;
&lt;br /&gt;
Для наилучшего решения этих проблем BIRCH распределяет входящие данные по кластерам динамически. Для эффективной кластеризации алгоритму требуется всего одно сканирование данных (т.е. с увеличением количества данных сложность увеличивается линейно). А при помощи одной (или более) дополнительных итераций можно и далее улучшать эффективность. BIRCH также является первым алгоритмом, предложенным для эффективного управления &amp;quot;шумами&amp;quot; (данными, которые не вписываются в общее представление модели).&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Теоретическая основа ===&lt;br /&gt;
&lt;br /&gt;
Пусть в кластере имеются &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}, i=1,2,...,N&amp;lt;/math&amp;gt;.&lt;br /&gt;
Тогда &#039;&#039;&#039;центроид&#039;&#039;&#039; &amp;lt;math&amp;gt;{\vec{{X_0}}}&amp;lt;/math&amp;gt;, &#039;&#039;&#039;радиус&#039;&#039;&#039; &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &#039;&#039;&#039;диаметр&#039;&#039;&#039; &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластера определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;{\vec{X_0}}=\frac{\sum_{i=1}^N\vec{X_i}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{\sum_{i=1}^N{(\vec{X_i} - \vec{X_0})}^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{\sum_{i=1}^N\sum_{j=1}^N{(\vec{X_i} - \vec{X_j})}^2}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; - это среднее расстояние от каждой точки до центроида. &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; - это среднее расстояние между парами в кластере. Данные величины являются альтернативными метриками плотности кластера относительно центроида.&lt;br /&gt;
&lt;br /&gt;
Для измерения близости друг к другу двух кластеров вводятся следующие метрики:&lt;br /&gt;
&lt;br /&gt;
пусть даны центроиды двух кластеров &amp;lt;math&amp;gt;\vec{X_{01}}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\vec{X_{02}}&amp;lt;/math&amp;gt;.&lt;br /&gt;
Евклидова метрика &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt; и метрика Манхэттена &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt; между двумя кластерами определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_0 = ((\vec{X_{01}}-\vec{X_{02}})^2)^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_1 = |\vec{X_{01}}-\vec{X_{02}}| = \sum_{i=1}^d |{\vec{X_{01}}}^{(i)}-{\vec{X_{02}}}^{(i)}| &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть имеются два кластера, содержащих соответственно  &amp;lt;math&amp;gt;N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;N_2&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i= 1,2, ...,N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\{\vec{X_j}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j= N_1+1,N_1+2, ...,N_1+N_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Среднее расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &#039;&#039;&#039;среднее внутрикластерное расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &#039;&#039;&#039;дисперсия&#039;&#039;&#039; &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; для двух кластеров определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{\sum_{i=1}^{N_1}\sum_{j=N_1+1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{N_1N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{\sum_{i=1}^{N_1+N_2}\sum_{j=1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_4 = \sum_{k=1}^{N_1+N_2}(\vec{X_k} - \frac{\sum_{i=1}^{N_1+N_2}\vec{X_i}}{N_1+N_2})^2 - \sum_{i=1}^{N_1}(\vec{X_i} - \frac{\sum_{i=1}^{N_1}\vec{X_i}}{N_1})^2 - \sum_{j=N_1+1}^{N_1+N_2}(\vec{X_j} - \frac{\sum_{i=N_1+1}^{N_1+N_2}\vec{X_i}}{N_2})^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Таким образом, величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; относятся к отдельным кластерам, а &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; - к объединению двух кластеров.&lt;br /&gt;
&lt;br /&gt;
=== Кластерный элемент и кластерное дерево ===&lt;br /&gt;
&lt;br /&gt;
В основе концепции алгоритма BIRCH лежат понятия &#039;&#039;&#039;кластерного элемента&#039;&#039;&#039; и &#039;&#039;&#039;кластерного дерева (CF Tree)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====Кластерный элемент ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; Пусть в кластере содержатся  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности  &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;:&amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;i=1,2,...,N&amp;lt;/math&amp;gt;. &lt;br /&gt;
&#039;&#039;&#039;Кластерный элемент (CF)&#039;&#039;&#039; - тройка чисел, характеризующая информацию о кластере: &lt;br /&gt;
&amp;lt;math&amp;gt;CF = (N, \vec{LS}, SS)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - количество элементов входных данных, содержащихся в кластере, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; - линейная сумма входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}\vec{X_i}&amp;lt;/math&amp;gt;), &amp;lt;math&amp;gt;SS&amp;lt;/math&amp;gt; - сумма квадратов входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}{\vec{X_i}}^2&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Теорема&#039;&#039;&#039; Пусть &amp;lt;math&amp;gt;CF_1 = (N_1, \vec{LS_1}, SS_1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;CF_2 = (N_1, \vec{LS_2}, SS_2)&amp;lt;/math&amp;gt; - CF векторы двух непересекающихся кластеров. Тогда при их объединении образуется кластер со следующим CF вектором: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF = CF_1 + CF_2 = (N_1+N_2, \vec{LS_1}+\vec{LS_2}, SS_1+SS_2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Из указанных выше определения и теоремы вытекает тот факт, что при объединении кластеров их CF вектор может вычисляться инкрементно и точно. &lt;br /&gt;
Легко показать, что вычислить величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;, как и обычные метрики, также не составит труда.&lt;br /&gt;
&lt;br /&gt;
Таким образом, в данном случае информацией о кластере является не весь набор точек, а вектор CF. Хранение одного только вектора может показаться неэффективным, но этого вполне достаточно для оперирования всеми необходимыми метриками, на основе которых принимаются решения в алгоритме BIRCH.&lt;br /&gt;
&lt;br /&gt;
==== Кластерное дерево ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; &#039;&#039;&#039;Кластерное дерево (CF Tree)&#039;&#039;&#039; - это взвешенно сбалансированное дерево с двумя параметрами: &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - коэффициент разветвления, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - пороговая величина. Каждый нелистьевой узел дерева имеет не более чем &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; вхождений узлов следующей формы: &amp;lt;math&amp;gt;[CF_i,child_i]&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i=1,2,...,B&amp;lt;/math&amp;gt;, &#039;&#039;child&#039;&#039; - указатель на i-й дочерний узел, &amp;lt;math&amp;gt;CF_i&amp;lt;/math&amp;gt; - CF вектор соответствующего подкластера.&lt;br /&gt;
&lt;br /&gt;
Каждый листьевой узел имеет ссылку на два соседних узла (&#039;&#039;prev&#039;&#039; и &#039;&#039;next&#039;&#039;) для того, чтобы связать все узлы для эффективного сканирования.&lt;br /&gt;
Все листьевые узлы должны удовлетворять пороговому ограничению &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, т.е. диаметр (радиус) не должен превосходить &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;.&lt;br /&gt;
В процессе вставки новых данных CF дерево строится динамически. Оно использует вставку данных для кластеризации точно также как &amp;lt;math&amp;gt;B+&amp;lt;/math&amp;gt; [https://ru.wikipedia.org/wiki/B%2B-%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE дерево] использует её для поиска.&lt;br /&gt;
CF дерево очень компактно, поскольку каждый листьевой узел - это не просто точка, а подкластер (который объединяет множество точек с учётом ограничения &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Операция вставки в &#039;&#039;&#039;CF&#039;&#039;&#039; дерево ====&lt;br /&gt;
&lt;br /&gt;
Опишем алгоритм вставки элемнта &amp;lt;math&amp;gt;Ent&amp;lt;/math&amp;gt; в CF дерево:&lt;br /&gt;
&lt;br /&gt;
1) &#039;&#039;Определение подходящего листа&#039;&#039;: Начиная с корня, алгоритм рекурсивно спускается по CF дереву, выбирая &#039;&#039;&#039;ближайший&#039;&#039;&#039; дочерний узел в соответствии с выбранной метрикой &amp;lt;math&amp;gt;D0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D4&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &#039;&#039;Преобразование листа&#039;&#039;: Когда алгоритм доходит до листа, он находит ближайшую листьевой элемент, скажем, &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;, а затем проверяет, можно ли добавить &#039;&#039;Ent&#039;&#039; к &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt; без нарушения порогового условия. Если да, то с учётом этого изменяется CF вектор для &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;; если нет, то &#039;&#039;Ent&#039;&#039; становится новым элементом листа. Если в листе для этого достаточно места, то шаг окончен, иначе он должен &amp;quot;расщепиться&amp;quot;. Расщепление узла производится при помощи выбора за основу наиболее удалённой друг от друга пары элементов и перераспределение оставшихся элементов в соответствии с выбранным критерием близости.&lt;br /&gt;
&lt;br /&gt;
3) &#039;&#039;Преобразование пути к листу&#039;&#039;: После вставки &#039;&#039;Ent&#039;&#039; в лист мы должны обновить информацию о CF для каждого нелистьевого элемента на пути к листу. При отсутствии расщепления это означает простое сложение CF векторов для отражения факта добавления &#039;&#039;Ent&#039;&#039;. Расщепление листа же требует вставки нового нелистьевого элемента в родительский узел для задания только что созданного листа. Если у родителя есть место для этого элемента, то необходимо просто преобразовать CF векторы на всех более высоких уровнях. В общем случае, однако, нам также придётся расщепить родительский узел, и так далее до корня. Если расщеплён корень, то высота дерева увеличивается на единицу.&lt;br /&gt;
&lt;br /&gt;
4) &#039;&#039;Улучшение слияния&#039;&#039;: Расщепление вызвано ограничением на размер узла, который не зависит от кластеризационных свойств данных. Если во входящем потоке присутствуют &amp;quot;искажённые&amp;quot; (из областей с низкой плотностью) данные, это может повлиять на качество кластеризации, а также уменьшить эффективность использования памяти. Дополнительный шаг алгоритма помогает решить эти проблемы: предположим, что произошло расщепление листа, и распространение этого процесса остановилось на некотором нелистьевом узле &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt;, то есть &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; может вместить дополнительный элемент, полученный после расщепления. Теперь мы сканируем узел &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; для нахождения двух наиболее близких элементов. Если это не пара, отвечающая расщеплению, мы пытаемся объединить их и поставить в соответствие два дочерних узла. Если количество элементов в дочерних узлах  больше B, мы снова расщепляем результат объединения.&lt;br /&gt;
В процессе повторного расщепления, в случае, если один источник собирает достаточно элементов для того, чтобы полностью заполнить узел, оставшиеся элементы передаются другом источнику. В итоге, если объединённые элементы помещаются в одном узле, в нём освобождается место для ещё одного элемента. Тем самым увеличивается степень использования свободного пространства и откладывается дальнейшее расщепление. В ином случае мы улучшаем распределение элементов в двух ближайших подкластерах.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро алгоритма заключается в многократном выполнении операции вставки нового элемента в дерево, в процессе чего требуется вычисление следующих величин:&lt;br /&gt;
&lt;br /&gt;
* радиуса &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; или диаметра &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластерного элемента. Выполняется при попытке вставить новый элемент в один из подкластеров листьевого узла дерева.&lt;br /&gt;
&lt;br /&gt;
* расстояния между двумя элементами. Выполняется при поиске ближайшего по отношению к новому элементу подкластера в узле дерева по одной из рассмотренных в разд. 1.2.1 метрик &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Зная характеристики кластерных элементов &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;, в результате алгебраических преобразований можно получить следующие упрощенные формулы вычисления необходимых значений:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\vec{X_0} = \frac{\vec{LS}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{SS - 2\vec{X_0}\vec{LS} + N(\vec{X_0})^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{2(N*SS - (\vec{LS})^2)}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{N_1*SS_2 + N_2*SS_1 - 2\vec{LS_1}\vec{LS_2}}{N_1*N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{2((N_1+N_2)(SS_1+SS_2)-(\vec{LS_1}+\vec{LS_2})^2)}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Реализация алгоритма BIRCH состояит из следующих четырёх фаз:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 1&#039;&#039;&#039;. Главной задачей фазы 1 является сканирование всех данных и построение в памяти исходного CF дерева, используя заданное количество памяти. Это дерево стремится отразить информацию о кластеризации данных настолько хорошо, насколько это позволяют ограничения по памяти. При этом плотно распределённые данные группируются в подкластеры, а более разрозненные данные удаляются. После завершения фазы 1 вспомогательные вычисления в дальнейших фазах будут:&lt;br /&gt;
&lt;br /&gt;
1) быстрее, потому что (а) больше не нужны операции ввода-вывода, (b) проблема кластеризации начальных данных упрощается до проблемы кластеризации подкластеров в листьях;&lt;br /&gt;
&lt;br /&gt;
2) точнее, потому что (а) большинство данных с низкой плотностью удалены, (b) оставшиеся данные распределены оптимально (в соответствии с доступным количеством памяти);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 2&#039;&#039;&#039;. Данная фаза является опциональной. Известно, что существующие методы глобальной кластеризации, используемые в рамках фазы 3, имеют различные диапазоны входных значений, при которых их реализация наиболее эффективна. Поэтому потенциально существует пробел между размером фазы 1 и входными значениями фазы 3. И фаза 2 как раз является недостающим связующим звеном: так же как и фаза 1, она сканирует листьевые элементы начального CF дерева для того, чтобы построить меньшее дерево, удаляя ещё больше элементов с низкой плотностью и группируя переполненные подкластеры в большие кластеры.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 3&#039;&#039;&#039;. В данной фазе для листьевых элементов применяется (любой подходящий) алгоритм глобальной кластеризации. Существующие алгоритмы кластеризации наборов точек могут также работать с наборами подкластеров, каждый из которых представлен своим CF вектором. Зная CF вектор, можно вычислить центроид и в дальнейшем заменить всю информацию о кластере этим значением (этого достаточно для вычисления большинства необходимых метрик). После фазы 3 мы получаем набор кластеров, который отражает основные характеристики распределяемых данных.&lt;br /&gt;
Однако, всё ещё могут оставаться некоторые неточности, для устранения которых существует фаза 4.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 4&#039;&#039;&#039;. Данная фаза является опциональной и влечёт за собой затраты на дополнительное сканирование данных для корректировки неточностей и дальнейшего улучшения кластеризации. Фаза 4 использует центроиды кластеров, полученные в фазе 3 для как основы и перераспределяет точки входных данных в ближайшие для них основы для получения нового списка кластеров. Фаза 4, если это необходимо пользователю, может быть расширена дополнительными проходами для уверенности в том, что результат приближается к оптимальному.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Для начала проанализируем вычислительную сложность фазы 1.&lt;br /&gt;
Максимальный размер дерева &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt;. Для того чтобы вставить элемент, мы должны пройти путь от корня до листа (это около &amp;lt;math&amp;gt;1+log_B\frac{M}{P}&amp;lt;/math&amp;gt; узлов). В каждом узле в поисках &amp;quot;ближайшего&amp;quot; нам необходимо просмотреть B элементов; сложность для каждого элемента пропорциональна размерности &#039;&#039;d&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Поэтому сложность вставки всех входных точек &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В случае, когда необходимо перестроить дерево, предположим, что ES - это размер CF элемента. Существует максимум &amp;lt;math&amp;gt;\frac{M}{ES}&amp;lt;/math&amp;gt; листьевых элементов для вставки, поэтому сложность повторной вставки листьевых элементов &amp;lt;math&amp;gt;O(d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Количество итераций перестройки дерева зависит от пороговой величины. На самом деле, это около &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; (двоичное основание появилось из-за того, что мы не можем провести оценку более чем в 2 раза отличающуюся от текущего размера). &amp;lt;math&amp;gt;N_0&amp;lt;/math&amp;gt; - это число входных точек, загруженных в память с пороговым ограничением &amp;lt;math&amp;gt;T_0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Соответственно, итоговая сложность фазы 1 &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P})+log_2\frac{N}{N_0}*d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Анализ фазы 2 проводится аналогично.&lt;br /&gt;
&lt;br /&gt;
Что касается операций ввода-вывода, то в фазе 1 данные сканируются один раз, а в фазе 2 не сканируются вовсе.&lt;br /&gt;
Некоторое количество вычислений связано с удалением точек из областей с низкой плотностью.&lt;br /&gt;
Если количество доступной для этой операции памяти не больше &#039;&#039;M&#039;&#039; и проведено порядка &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; перестроек дерева, то сложность ввода-вывода для фазы 1 существенно не отличается от сложности чтения из файла. Основываясь рассуждениях выше, сложность фаз 1 и 2 будет линейно увеличиваться с ростом N.&lt;br /&gt;
&lt;br /&gt;
В фазе 3 нет операций ввода-вывода. Её сложность ограничена константой, которая зависит от максимального размера входных данных, и варианта выбранного алгоритма для кластеризации. &lt;br /&gt;
&lt;br /&gt;
Фаза 4 снова сканирует данные и записывает каждую точку в подходящий кластер; время работы пропорционально &amp;lt;math&amp;gt;N*K&amp;lt;/math&amp;gt;.   &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Достоинства алгоритма ===&lt;br /&gt;
По сравнению с предыдущими методами BIRCH обладает следующими достоинствами:&lt;br /&gt;
&lt;br /&gt;
1. BIRCH является локальным алгоритмом, то есть каждое решение о каждом элементе кластера принимается без повторного сканирования данных или уже существующих кластеров. Используются только метрики, отражающие близость элементов друг к другу.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH использует факт неравномерного распределения данных в пространстве и поэтому не все данные рассматриваются как одинаково важные для построения кластера. Области с большой плотностью обрабатываются как единый кластер. Данные в более разреженных областях могут удаляться (опционально).&lt;br /&gt;
&lt;br /&gt;
3. BIRCH использует всю доступную память для получения наилучших из возможных подкластеров, в то же время минимизируя затраты на операции ввода/вывода. Оптимизация процесса кластеризации достигается за счет использования взвешенно-сбалансированного дерева. При этом время исполнения линейно.&lt;br /&gt;
&lt;br /&gt;
4. BIRCH не требует всего набора данных заранее (при этом просматривает его всего один раз).&lt;br /&gt;
&lt;br /&gt;
=== Недостатки алгоритма ===&lt;br /&gt;
&lt;br /&gt;
1. Алгоритм позволяет работать только с числовыми данными.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH хорошо выделяет только кластеры сферической формы.&lt;br /&gt;
&lt;br /&gt;
3. Существует необходимость в задании пороговых значений.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* [https://code.google.com/archive/p/jbirch/ Java]&lt;br /&gt;
* [http://scikit-learn.org/stable/modules/generated/sklearn.cluster.Birch.html Python]&lt;br /&gt;
* [http://cucis.ece.northwestern.edu/projects/DMS/MineBench.html#description]&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&lt;br /&gt;
* [https://en.wikipedia.org/wiki/BIRCH Википедия] &lt;br /&gt;
* [http://www.cs.sfu.ca/CourseCentral/459/han/papers/zhang96.pdf T Zhang, R Ramakrishnan, M Livny. BIRCH: An Efficient Data Clustering Method for Very Large Databases]&lt;br /&gt;
* [http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf Нейский И.М. Классификация и сравнение методов кластеризации]&lt;br /&gt;
* [http://people.du.ac.in/~ngupta/Publications/PBIRCH%20A%20Sacalabel%20Paralllel%20Clustering.pdf A Garg, N Gupta PBIRCH: A Scalable Parallel Clustering algorithm for Incremental Data]&lt;/div&gt;</summary>
		<author><name>Светлана Морозова</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13535</id>
		<title>Участник:Smirnov.maxim/BIRCH</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13535"/>
		<updated>2016-10-23T16:48:10Z</updated>

		<summary type="html">&lt;p&gt;Светлана Морозова: /* Литература */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Нахождение полезных для анализа закономерностей в больших объёмах данных с недавних пор вызывает значительный интерес. В связи с этим ввелось и стало активно развиваться такое понятие как &#039;&#039;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7 кластеризация]&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Ранние работы и алгоритмы, разработанные в этой области, не уделяли достаточного внимания анализу очень больших наборов данных или минимизации издержек на процессы ввода-вывода.&lt;br /&gt;
Решением этих проблем стал алгоритм, известный как BIRCH.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIRCH&#039;&#039;&#039; (balanced iterative reducing and clustering using hierarchies)- алгоритм, применяемый в области [https://ru.wikipedia.org/wiki/Data_mining Data mining] и использующий принципы [https://ru.wikipedia.org/wiki/%D0%98%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F иерархической кластеризации].&lt;br /&gt;
&lt;br /&gt;
Если имеется очень большой набор данных, то в пространстве он распределен, как правило, неравномерно. Кластерный анализ определяет места наибольшего и наименьшего скоплений, чтобы таким образом понять всю картину целиком. Кроме того, полученные кластеры визуализируются гораздо нагляднее, чем начальные &amp;quot;сырые&amp;quot; данные.&lt;br /&gt;
Задачей алгоритмов кластеризации является не только простое разбиение данных на кластеры, но и работа в рамках ограниченного объёма доступной памяти (как правило, её объём гораздо меньше, чем размер исходного набора данных) и минимизация времени, требуемого на операции ввода-вывода.&lt;br /&gt;
&lt;br /&gt;
Для наилучшего решения этих проблем BIRCH распределяет входящие данные по кластерам динамически. Для эффективной кластеризации алгоритму требуется всего одно сканирование данных (т.е. с увеличением количества данных сложность увеличивается линейно). А при помощи одной (или более) дополнительных итераций можно и далее улучшать эффективность. BIRCH также является первым алгоритмом, предложенным для эффективного управления &amp;quot;шумами&amp;quot; (данными, которые не вписываются в общее представление модели).&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Теоретическая основа ===&lt;br /&gt;
&lt;br /&gt;
Пусть в кластере имеются &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}, i=1,2,...,N&amp;lt;/math&amp;gt;.&lt;br /&gt;
Тогда &#039;&#039;&#039;центроид&#039;&#039;&#039; &amp;lt;math&amp;gt;{\vec{{X_0}}}&amp;lt;/math&amp;gt;, &#039;&#039;&#039;радиус&#039;&#039;&#039; &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &#039;&#039;&#039;диаметр&#039;&#039;&#039; &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластера определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;{\vec{X_0}}=\frac{\sum_{i=1}^N\vec{X_i}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{\sum_{i=1}^N{(\vec{X_i} - \vec{X_0})}^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{\sum_{i=1}^N\sum_{j=1}^N{(\vec{X_i} - \vec{X_j})}^2}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; - это среднее расстояние от каждой точки до центроида. &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; - это среднее расстояние между парами в кластере. Данные величины являются альтернативными метриками плотности кластера относительно центроида.&lt;br /&gt;
&lt;br /&gt;
Для измерения близости друг к другу двух кластеров вводятся следующие метрики:&lt;br /&gt;
&lt;br /&gt;
пусть даны центроиды двух кластеров &amp;lt;math&amp;gt;\vec{X_{01}}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\vec{X_{02}}&amp;lt;/math&amp;gt;.&lt;br /&gt;
Евклидова метрика &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt; и метрика Манхэттена &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt; между двумя кластерами определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_0 = ((\vec{X_{01}}-\vec{X_{02}})^2)^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_1 = |\vec{X_{01}}-\vec{X_{02}}| = \sum_{i=1}^d |{\vec{X_{01}}}^{(i)}-{\vec{X_{02}}}^{(i)}| &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть имеются два кластера, содержащих соответственно  &amp;lt;math&amp;gt;N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;N_2&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i= 1,2, ...,N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\{\vec{X_j}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j= N_1+1,N_1+2, ...,N_1+N_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Среднее расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &#039;&#039;&#039;среднее внутрикластерное расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &#039;&#039;&#039;дисперсия&#039;&#039;&#039; &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; для двух кластеров определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{\sum_{i=1}^{N_1}\sum_{j=N_1+1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{N_1N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{\sum_{i=1}^{N_1+N_2}\sum_{j=1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_4 = \sum_{k=1}^{N_1+N_2}(\vec{X_k} - \frac{\sum_{i=1}^{N_1+N_2}\vec{X_i}}{N_1+N_2})^2 - \sum_{i=1}^{N_1}(\vec{X_i} - \frac{\sum_{i=1}^{N_1}\vec{X_i}}{N_1})^2 - \sum_{j=N_1+1}^{N_1+N_2}(\vec{X_j} - \frac{\sum_{i=N_1+1}^{N_1+N_2}\vec{X_i}}{N_2})^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Таким образом, величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; относятся к отдельным кластерам, а &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; - к объединению двух кластеров.&lt;br /&gt;
&lt;br /&gt;
=== Кластерный элемент и кластерное дерево ===&lt;br /&gt;
&lt;br /&gt;
В основе концепции алгоритма BIRCH лежат понятия &#039;&#039;&#039;кластерного элемента&#039;&#039;&#039; и &#039;&#039;&#039;кластерного дерева (CF Tree)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====Кластерный элемент ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; Пусть в кластере содержатся  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности  &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;:&amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;i=1,2,...,N&amp;lt;/math&amp;gt;. &lt;br /&gt;
&#039;&#039;&#039;Кластерный элемент (CF)&#039;&#039;&#039; - тройка чисел, характеризующая информацию о кластере: &lt;br /&gt;
&amp;lt;math&amp;gt;CF = (N, \vec{LS}, SS)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - количество элементов входных данных, содержащихся в кластере, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; - линейная сумма входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}\vec{X_i}&amp;lt;/math&amp;gt;), &amp;lt;math&amp;gt;SS&amp;lt;/math&amp;gt; - сумма квадратов входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}{\vec{X_i}}^2&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Теорема&#039;&#039;&#039; Пусть &amp;lt;math&amp;gt;CF_1 = (N_1, \vec{LS_1}, SS_1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;CF_2 = (N_1, \vec{LS_2}, SS_2)&amp;lt;/math&amp;gt; - CF векторы двух непересекающихся кластеров. Тогда при их объединении образуется кластер со следующим CF вектором: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF = CF_1 + CF_2 = (N_1+N_2, \vec{LS_1}+\vec{LS_2}, SS_1+SS_2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Из указанных выше определения и теоремы вытекает тот факт, что при объединении кластеров их CF вектор может вычисляться инкрементно и точно. &lt;br /&gt;
Легко показать, что вычислить величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;, как и обычные метрики, также не составит труда.&lt;br /&gt;
&lt;br /&gt;
Таким образом, в данном случае информацией о кластере является не весь набор точек, а вектор CF. Хранение одного только вектора может показаться неэффективным, но этого вполне достаточно для оперирования всеми необходимыми метриками, на основе которых принимаются решения в алгоритме BIRCH.&lt;br /&gt;
&lt;br /&gt;
==== Кластерное дерево ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; &#039;&#039;&#039;Кластерное дерево (CF Tree)&#039;&#039;&#039; - это взвешенно сбалансированное дерево с двумя параметрами: &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - коэффициент разветвления, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - пороговая величина. Каждый нелистьевой узел дерева имеет не более чем &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; вхождений узлов следующей формы: &amp;lt;math&amp;gt;[CF_i,child_i]&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i=1,2,...,B&amp;lt;/math&amp;gt;, &#039;&#039;child&#039;&#039; - указатель на i-й дочерний узел, &amp;lt;math&amp;gt;CF_i&amp;lt;/math&amp;gt; - CF вектор соответствующего подкластера.&lt;br /&gt;
&lt;br /&gt;
Каждый листьевой узел имеет ссылку на два соседних узла (&#039;&#039;prev&#039;&#039; и &#039;&#039;next&#039;&#039;) для того, чтобы связать все узлы для эффективного сканирования.&lt;br /&gt;
Все листьевые узлы должны удовлетворять пороговому ограничению &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, т.е. диаметр (радиус) не должен превосходить &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;.&lt;br /&gt;
В процессе вставки новых данных CF дерево строится динамически. Оно использует вставку данных для кластеризации точно также как &amp;lt;math&amp;gt;B+&amp;lt;/math&amp;gt; [https://ru.wikipedia.org/wiki/B%2B-%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE дерево] использует её для поиска.&lt;br /&gt;
CF дерево очень компактно, поскольку каждый листьевой узел - это не просто точка, а подкластер (который объединяет множество точек с учётом ограничения &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Операция вставки в &#039;&#039;&#039;CF&#039;&#039;&#039; дерево ====&lt;br /&gt;
&lt;br /&gt;
Опишем алгоритм вставки элемнта &amp;lt;math&amp;gt;Ent&amp;lt;/math&amp;gt; в CF дерево:&lt;br /&gt;
&lt;br /&gt;
1) &#039;&#039;Определение подходящего листа&#039;&#039;: Начиная с корня, алгоритм рекурсивно спускается по CF дереву, выбирая &#039;&#039;&#039;ближайший&#039;&#039;&#039; дочерний узел в соответствии с выбранной метрикой &amp;lt;math&amp;gt;D0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D4&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &#039;&#039;Преобразование листа&#039;&#039;: Когда алгоритм доходит до листа, он находит ближайшую листьевой элемент, скажем, &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;, а затем проверяет, можно ли добавить &#039;&#039;Ent&#039;&#039; к &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt; без нарушения порогового условия. Если да, то с учётом этого изменяется CF вектор для &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;; если нет, то &#039;&#039;Ent&#039;&#039; становится новым элементом листа. Если в листе для этого достаточно места, то шаг окончен, иначе он должен &amp;quot;расщепиться&amp;quot;. Расщепление узла производится при помощи выбора за основу наиболее удалённой друг от друга пары элементов и перераспределение оставшихся элементов в соответствии с выбранным критерием близости.&lt;br /&gt;
&lt;br /&gt;
3) &#039;&#039;Преобразование пути к листу&#039;&#039;: После вставки &#039;&#039;Ent&#039;&#039; в лист мы должны обновить информацию о CF для каждого нелистьевого элемента на пути к листу. При отсутствии расщепления это означает простое сложение CF векторов для отражения факта добавления &#039;&#039;Ent&#039;&#039;. Расщепление листа же требует вставки нового нелистьевого элемента в родительский узел для задания только что созданного листа. Если у родителя есть место для этого элемента, то необходимо просто преобразовать CF векторы на всех более высоких уровнях. В общем случае, однако, нам также придётся расщепить родительский узел, и так далее до корня. Если расщеплён корень, то высота дерева увеличивается на единицу.&lt;br /&gt;
&lt;br /&gt;
4) &#039;&#039;Улучшение слияния&#039;&#039;: Расщепление вызвано ограничением на размер узла, который не зависит от кластеризационных свойств данных. Если во входящем потоке присутствуют &amp;quot;искажённые&amp;quot; (из областей с низкой плотностью) данные, это может повлиять на качество кластеризации, а также уменьшить эффективность использования памяти. Дополнительный шаг алгоритма помогает решить эти проблемы: предположим, что произошло расщепление листа, и распространение этого процесса остановилось на некотором нелистьевом узле &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt;, то есть &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; может вместить дополнительный элемент, полученный после расщепления. Теперь мы сканируем узел &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; для нахождения двух наиболее близких элементов. Если это не пара, отвечающая расщеплению, мы пытаемся объединить их и поставить в соответствие два дочерних узла. Если количество элементов в дочерних узлах  больше B, мы снова расщепляем результат объединения.&lt;br /&gt;
В процессе повторного расщепления, в случае, если один источник собирает достаточно элементов для того, чтобы полностью заполнить узел, оставшиеся элементы передаются другом источнику. В итоге, если объединённые элементы помещаются в одном узле, в нём освобождается место для ещё одного элемента. Тем самым увеличивается степень использования свободного пространства и откладывается дальнейшее расщепление. В ином случае мы улучшаем распределение элементов в двух ближайших подкластерах.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро алгоритма заключается в многократном выполнении операции вставки нового элемента в дерево, в процессе чего требуется вычисление следующих величин:&lt;br /&gt;
&lt;br /&gt;
* радиуса &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; или диаметра &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластерного элемента. Выполняется при попытке вставить новый элемент в один из подкластеров листьевого узла дерева.&lt;br /&gt;
&lt;br /&gt;
* расстояния между двумя элементами. Выполняется при поиске ближайшего по отношению к новому элементу подкластера в узле дерева по одной из рассмотренных в разд. 1.2.1 метрик &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Зная характеристики кластерных элементов &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;, в результате алгебраических преобразований можно получить следующие упрощенные формулы вычисления необходимых значений:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\vec{X_0} = \frac{\vec{LS}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{SS - 2\vec{X_0}\vec{LS} + N(\vec{X_0})^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{2(N*SS - (\vec{LS})^2)}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{N_1*SS_2 + N_2*SS_1 - 2\vec{LS_1}\vec{LS_2}}{N_1*N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{2((N_1+N_2)(SS_1+SS_2)-(\vec{LS_1}+\vec{LS_2})^2)}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Реализация алгоритма BIRCH состояит из следующих четырёх фаз:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 1&#039;&#039;&#039;. Главной задачей фазы 1 является сканирование всех данных и построение в памяти исходного CF дерева, используя заданное количество памяти. Это дерево стремится отразить информацию о кластеризации данных настолько хорошо, насколько это позволяют ограничения по памяти. При этом плотно распределённые данные группируются в подкластеры, а более разрозненные данные удаляются. После завершения фазы 1 вспомогательные вычисления в дальнейших фазах будут:&lt;br /&gt;
&lt;br /&gt;
1) быстрее, потому что (а) больше не нужны операции ввода-вывода, (b) проблема кластеризации начальных данных упрощается до проблемы кластеризации подкластеров в листьях;&lt;br /&gt;
&lt;br /&gt;
2) точнее, потому что (а) большинство данных с низкой плотностью удалены, (b) оставшиеся данные распределены оптимально (в соответствии с доступным количеством памяти);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 2&#039;&#039;&#039;. Данная фаза является опциональной. Известно, что существующие методы глобальной кластеризации, используемые в рамках фазы 3, имеют различные диапазоны входных значений, при которых их реализация наиболее эффективна. Поэтому потенциально существует пробел между размером фазы 1 и входными значениями фазы 3. И фаза 2 как раз является недостающим связующим звеном: так же как и фаза 1, она сканирует листьевые элементы начального CF дерева для того, чтобы построить меньшее дерево, удаляя ещё больше элементов с низкой плотностью и группируя переполненные подкластеры в большие кластеры.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 3&#039;&#039;&#039;. В данной фазе для листьевых элементов применяется (любой подходящий) алгоритм глобальной кластеризации. Существующие алгоритмы кластеризации наборов точек могут также работать с наборами подкластеров, каждый из которых представлен своим CF вектором. Зная CF вектор, можно вычислить центроид и в дальнейшем заменить всю информацию о кластере этим значением (этого достаточно для вычисления большинства необходимых метрик). После фазы 3 мы получаем набор кластеров, который отражает основные характеристики распределяемых данных.&lt;br /&gt;
Однако, всё ещё могут оставаться некоторые неточности, для устранения которых существует фаза 4.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 4&#039;&#039;&#039;. Данная фаза является опциональной и влечёт за собой затраты на дополнительное сканирование данных для корректировки неточностей и дальнейшего улучшения кластеризации. Фаза 4 использует центроиды кластеров, полученные в фазе 3 для как основы и перераспределяет точки входных данных в ближайшие для них основы для получения нового списка кластеров. Фаза 4, если это необходимо пользователю, может быть расширена дополнительными проходами для уверенности в том, что результат приближается к оптимальному.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Для начала проанализируем вычислительную сложность фазы 1.&lt;br /&gt;
Максимальный размер дерева &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt;. Для того чтобы вставить элемент, мы должны пройти путь от корня до листа (это около &amp;lt;math&amp;gt;1+log_B\frac{M}{P}&amp;lt;/math&amp;gt; узлов). В каждом узле в поисках &amp;quot;ближайшего&amp;quot; нам необходимо просмотреть B элементов; сложность для каждого элемента пропорциональна размерности &#039;&#039;d&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Поэтому сложность вставки всех входных точек &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В случае, когда необходимо перестроить дерево, предположим, что ES - это размер CF элемента. Существует максимум &amp;lt;math&amp;gt;\frac{M}{ES}&amp;lt;/math&amp;gt; листьевых элементов для вставки, поэтому сложность повторной вставки листьевых элементов &amp;lt;math&amp;gt;O(d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Количество итераций перестройки дерева зависит от пороговой величины. На самом деле, это около &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; (двоичное основание появилось из-за того, что мы не можем провести оценку более чем в 2 раза отличающуюся от текущего размера). &amp;lt;math&amp;gt;N_0&amp;lt;/math&amp;gt; - это число входных точек, загруженных в память с пороговым ограничением &amp;lt;math&amp;gt;T_0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Соответственно, итоговая сложность фазы 1 &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P})+log_2\frac{N}{N_0}*d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Анализ фазы 2 проводится аналогично.&lt;br /&gt;
&lt;br /&gt;
Что касается операций ввода-вывода, то в фазе 1 данные сканируются один раз, а в фазе 2 не сканируются вовсе.&lt;br /&gt;
Некоторое количество вычислений связано с удалением точек из областей с низкой плотностью.&lt;br /&gt;
Если количество доступной для этой операции памяти не больше &#039;&#039;M&#039;&#039; и проведено порядка &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; перестроек дерева, то сложность ввода-вывода для фазы 1 существенно не отличается от сложности чтения из файла. Основываясь рассуждениях выше, сложность фаз 1 и 2 будет линейно увеличиваться с ростом N.&lt;br /&gt;
&lt;br /&gt;
В фазе 3 нет операций ввода-вывода. Её сложность ограничена константой, которая зависит от максимального размера входных данных, и варианта выбранного алгоритма для кластеризации. &lt;br /&gt;
&lt;br /&gt;
Фаза 4 снова сканирует данные и записывает каждую точку в подходящий кластер; время работы пропорционально &amp;lt;math&amp;gt;N*K&amp;lt;/math&amp;gt;.   &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Достоинства алгоритма ===&lt;br /&gt;
По сравнению с предыдущими методами BIRCH обладает следующими достоинствами:&lt;br /&gt;
&lt;br /&gt;
1. BIRCH является локальным алгоритмом, то есть каждое решение о каждом элементе кластера принимается без повторного сканирования данных или уже существующих кластеров. Используются только метрики, отражающие близость элементов друг к другу.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH использует факт неравномерного распределения данных в пространстве и поэтому не все данные рассматриваются как одинаково важные для построения кластера. Области с большой плотностью обрабатываются как единый кластер. Данные в более разреженных областях могут удаляться (опционально).&lt;br /&gt;
&lt;br /&gt;
3. BIRCH использует всю доступную память для получения наилучших из возможных подкластеров, в то же время минимизируя затраты на операции ввода/вывода. Оптимизация процесса кластеризации достигается за счет использования взвешенно-сбалансированного дерева. При этом время исполнения линейно.&lt;br /&gt;
&lt;br /&gt;
4. BIRCH не требует всего набора данных заранее (при этом просматривает его всего один раз).&lt;br /&gt;
&lt;br /&gt;
=== Недостатки алгоритма ===&lt;br /&gt;
&lt;br /&gt;
1. Алгоритм позволяет работать только с числовыми данными.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH хорошо выделяет только кластеры сферической формы.&lt;br /&gt;
&lt;br /&gt;
3. Существует необходимость в задании пороговых значений.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* [https://code.google.com/archive/p/jbirch/ Java]&lt;br /&gt;
* [http://scikit-learn.org/stable/modules/generated/sklearn.cluster.Birch.html Python]&lt;br /&gt;
* [http://cucis.ece.northwestern.edu/projects/DMS/MineBench.html#description]&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&lt;br /&gt;
* [https://en.wikipedia.org/wiki/BIRCH Википедия] &lt;br /&gt;
* [http://www.cs.sfu.ca/CourseCentral/459/han/papers/zhang96.pdf T Zhang, R Ramakrishnan, M Livny. BIRCH: An Efficient Data Clustering Method for Very Large Databases&lt;br /&gt;
* [http://it-claim.ru/Persons/Neyskiy/Article2_Neiskiy.pdf Нейский И.М. Классификация и сравнение методов кластеризации]&lt;br /&gt;
* [http://people.du.ac.in/~ngupta/Publications/PBIRCH%20A%20Sacalabel%20Paralllel%20Clustering.pdf A Garg, N Gupta PBIRCH: A Scalable Parallel Clustering algorithm for Incremental Data]&lt;/div&gt;</summary>
		<author><name>Светлана Морозова</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13534</id>
		<title>Участник:Smirnov.maxim/BIRCH</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13534"/>
		<updated>2016-10-23T16:35:20Z</updated>

		<summary type="html">&lt;p&gt;Светлана Морозова: /* Макроструктура алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Нахождение полезных для анализа закономерностей в больших объёмах данных с недавних пор вызывает значительный интерес. В связи с этим ввелось и стало активно развиваться такое понятие как &#039;&#039;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7 кластеризация]&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Ранние работы и алгоритмы, разработанные в этой области, не уделяли достаточного внимания анализу очень больших наборов данных или минимизации издержек на процессы ввода-вывода.&lt;br /&gt;
Решением этих проблем стал алгоритм, известный как BIRCH.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIRCH&#039;&#039;&#039; (balanced iterative reducing and clustering using hierarchies)- алгоритм, применяемый в области [https://ru.wikipedia.org/wiki/Data_mining Data mining] и использующий принципы [https://ru.wikipedia.org/wiki/%D0%98%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F иерархической кластеризации].&lt;br /&gt;
&lt;br /&gt;
Если имеется очень большой набор данных, то в пространстве он распределен, как правило, неравномерно. Кластерный анализ определяет места наибольшего и наименьшего скоплений, чтобы таким образом понять всю картину целиком. Кроме того, полученные кластеры визуализируются гораздо нагляднее, чем начальные &amp;quot;сырые&amp;quot; данные.&lt;br /&gt;
Задачей алгоритмов кластеризации является не только простое разбиение данных на кластеры, но и работа в рамках ограниченного объёма доступной памяти (как правило, её объём гораздо меньше, чем размер исходного набора данных) и минимизация времени, требуемого на операции ввода-вывода.&lt;br /&gt;
&lt;br /&gt;
Для наилучшего решения этих проблем BIRCH распределяет входящие данные по кластерам динамически. Для эффективной кластеризации алгоритму требуется всего одно сканирование данных (т.е. с увеличением количества данных сложность увеличивается линейно). А при помощи одной (или более) дополнительных итераций можно и далее улучшать эффективность. BIRCH также является первым алгоритмом, предложенным для эффективного управления &amp;quot;шумами&amp;quot; (данными, которые не вписываются в общее представление модели).&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Теоретическая основа ===&lt;br /&gt;
&lt;br /&gt;
Пусть в кластере имеются &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}, i=1,2,...,N&amp;lt;/math&amp;gt;.&lt;br /&gt;
Тогда &#039;&#039;&#039;центроид&#039;&#039;&#039; &amp;lt;math&amp;gt;{\vec{{X_0}}}&amp;lt;/math&amp;gt;, &#039;&#039;&#039;радиус&#039;&#039;&#039; &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &#039;&#039;&#039;диаметр&#039;&#039;&#039; &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластера определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;{\vec{X_0}}=\frac{\sum_{i=1}^N\vec{X_i}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{\sum_{i=1}^N{(\vec{X_i} - \vec{X_0})}^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{\sum_{i=1}^N\sum_{j=1}^N{(\vec{X_i} - \vec{X_j})}^2}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; - это среднее расстояние от каждой точки до центроида. &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; - это среднее расстояние между парами в кластере. Данные величины являются альтернативными метриками плотности кластера относительно центроида.&lt;br /&gt;
&lt;br /&gt;
Для измерения близости друг к другу двух кластеров вводятся следующие метрики:&lt;br /&gt;
&lt;br /&gt;
пусть даны центроиды двух кластеров &amp;lt;math&amp;gt;\vec{X_{01}}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\vec{X_{02}}&amp;lt;/math&amp;gt;.&lt;br /&gt;
Евклидова метрика &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt; и метрика Манхэттена &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt; между двумя кластерами определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_0 = ((\vec{X_{01}}-\vec{X_{02}})^2)^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_1 = |\vec{X_{01}}-\vec{X_{02}}| = \sum_{i=1}^d |{\vec{X_{01}}}^{(i)}-{\vec{X_{02}}}^{(i)}| &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть имеются два кластера, содержащих соответственно  &amp;lt;math&amp;gt;N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;N_2&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i= 1,2, ...,N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\{\vec{X_j}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j= N_1+1,N_1+2, ...,N_1+N_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Среднее расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &#039;&#039;&#039;среднее внутрикластерное расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &#039;&#039;&#039;дисперсия&#039;&#039;&#039; &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; для двух кластеров определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{\sum_{i=1}^{N_1}\sum_{j=N_1+1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{N_1N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{\sum_{i=1}^{N_1+N_2}\sum_{j=1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_4 = \sum_{k=1}^{N_1+N_2}(\vec{X_k} - \frac{\sum_{i=1}^{N_1+N_2}\vec{X_i}}{N_1+N_2})^2 - \sum_{i=1}^{N_1}(\vec{X_i} - \frac{\sum_{i=1}^{N_1}\vec{X_i}}{N_1})^2 - \sum_{j=N_1+1}^{N_1+N_2}(\vec{X_j} - \frac{\sum_{i=N_1+1}^{N_1+N_2}\vec{X_i}}{N_2})^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Таким образом, величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; относятся к отдельным кластерам, а &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; - к объединению двух кластеров.&lt;br /&gt;
&lt;br /&gt;
=== Кластерный элемент и кластерное дерево ===&lt;br /&gt;
&lt;br /&gt;
В основе концепции алгоритма BIRCH лежат понятия &#039;&#039;&#039;кластерного элемента&#039;&#039;&#039; и &#039;&#039;&#039;кластерного дерева (CF Tree)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====Кластерный элемент ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; Пусть в кластере содержатся  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности  &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;:&amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;i=1,2,...,N&amp;lt;/math&amp;gt;. &lt;br /&gt;
&#039;&#039;&#039;Кластерный элемент (CF)&#039;&#039;&#039; - тройка чисел, характеризующая информацию о кластере: &lt;br /&gt;
&amp;lt;math&amp;gt;CF = (N, \vec{LS}, SS)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - количество элементов входных данных, содержащихся в кластере, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; - линейная сумма входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}\vec{X_i}&amp;lt;/math&amp;gt;), &amp;lt;math&amp;gt;SS&amp;lt;/math&amp;gt; - сумма квадратов входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}{\vec{X_i}}^2&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Теорема&#039;&#039;&#039; Пусть &amp;lt;math&amp;gt;CF_1 = (N_1, \vec{LS_1}, SS_1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;CF_2 = (N_1, \vec{LS_2}, SS_2)&amp;lt;/math&amp;gt; - CF векторы двух непересекающихся кластеров. Тогда при их объединении образуется кластер со следующим CF вектором: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF = CF_1 + CF_2 = (N_1+N_2, \vec{LS_1}+\vec{LS_2}, SS_1+SS_2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Из указанных выше определения и теоремы вытекает тот факт, что при объединении кластеров их CF вектор может вычисляться инкрементно и точно. &lt;br /&gt;
Легко показать, что вычислить величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;, как и обычные метрики, также не составит труда.&lt;br /&gt;
&lt;br /&gt;
Таким образом, в данном случае информацией о кластере является не весь набор точек, а вектор CF. Хранение одного только вектора может показаться неэффективным, но этого вполне достаточно для оперирования всеми необходимыми метриками, на основе которых принимаются решения в алгоритме BIRCH.&lt;br /&gt;
&lt;br /&gt;
==== Кластерное дерево ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; &#039;&#039;&#039;Кластерное дерево (CF Tree)&#039;&#039;&#039; - это взвешенно сбалансированное дерево с двумя параметрами: &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - коэффициент разветвления, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - пороговая величина. Каждый нелистьевой узел дерева имеет не более чем &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; вхождений узлов следующей формы: &amp;lt;math&amp;gt;[CF_i,child_i]&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i=1,2,...,B&amp;lt;/math&amp;gt;, &#039;&#039;child&#039;&#039; - указатель на i-й дочерний узел, &amp;lt;math&amp;gt;CF_i&amp;lt;/math&amp;gt; - CF вектор соответствующего подкластера.&lt;br /&gt;
&lt;br /&gt;
Каждый листьевой узел имеет ссылку на два соседних узла (&#039;&#039;prev&#039;&#039; и &#039;&#039;next&#039;&#039;) для того, чтобы связать все узлы для эффективного сканирования.&lt;br /&gt;
Все листьевые узлы должны удовлетворять пороговому ограничению &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, т.е. диаметр (радиус) не должен превосходить &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;.&lt;br /&gt;
В процессе вставки новых данных CF дерево строится динамически. Оно использует вставку данных для кластеризации точно также как &amp;lt;math&amp;gt;B+&amp;lt;/math&amp;gt; [https://ru.wikipedia.org/wiki/B%2B-%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE дерево] использует её для поиска.&lt;br /&gt;
CF дерево очень компактно, поскольку каждый листьевой узел - это не просто точка, а подкластер (который объединяет множество точек с учётом ограничения &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Операция вставки в &#039;&#039;&#039;CF&#039;&#039;&#039; дерево ====&lt;br /&gt;
&lt;br /&gt;
Опишем алгоритм вставки элемнта &amp;lt;math&amp;gt;Ent&amp;lt;/math&amp;gt; в CF дерево:&lt;br /&gt;
&lt;br /&gt;
1) &#039;&#039;Определение подходящего листа&#039;&#039;: Начиная с корня, алгоритм рекурсивно спускается по CF дереву, выбирая &#039;&#039;&#039;ближайший&#039;&#039;&#039; дочерний узел в соответствии с выбранной метрикой &amp;lt;math&amp;gt;D0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D4&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &#039;&#039;Преобразование листа&#039;&#039;: Когда алгоритм доходит до листа, он находит ближайшую листьевой элемент, скажем, &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;, а затем проверяет, можно ли добавить &#039;&#039;Ent&#039;&#039; к &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt; без нарушения порогового условия. Если да, то с учётом этого изменяется CF вектор для &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;; если нет, то &#039;&#039;Ent&#039;&#039; становится новым элементом листа. Если в листе для этого достаточно места, то шаг окончен, иначе он должен &amp;quot;расщепиться&amp;quot;. Расщепление узла производится при помощи выбора за основу наиболее удалённой друг от друга пары элементов и перераспределение оставшихся элементов в соответствии с выбранным критерием близости.&lt;br /&gt;
&lt;br /&gt;
3) &#039;&#039;Преобразование пути к листу&#039;&#039;: После вставки &#039;&#039;Ent&#039;&#039; в лист мы должны обновить информацию о CF для каждого нелистьевого элемента на пути к листу. При отсутствии расщепления это означает простое сложение CF векторов для отражения факта добавления &#039;&#039;Ent&#039;&#039;. Расщепление листа же требует вставки нового нелистьевого элемента в родительский узел для задания только что созданного листа. Если у родителя есть место для этого элемента, то необходимо просто преобразовать CF векторы на всех более высоких уровнях. В общем случае, однако, нам также придётся расщепить родительский узел, и так далее до корня. Если расщеплён корень, то высота дерева увеличивается на единицу.&lt;br /&gt;
&lt;br /&gt;
4) &#039;&#039;Улучшение слияния&#039;&#039;: Расщепление вызвано ограничением на размер узла, который не зависит от кластеризационных свойств данных. Если во входящем потоке присутствуют &amp;quot;искажённые&amp;quot; (из областей с низкой плотностью) данные, это может повлиять на качество кластеризации, а также уменьшить эффективность использования памяти. Дополнительный шаг алгоритма помогает решить эти проблемы: предположим, что произошло расщепление листа, и распространение этого процесса остановилось на некотором нелистьевом узле &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt;, то есть &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; может вместить дополнительный элемент, полученный после расщепления. Теперь мы сканируем узел &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; для нахождения двух наиболее близких элементов. Если это не пара, отвечающая расщеплению, мы пытаемся объединить их и поставить в соответствие два дочерних узла. Если количество элементов в дочерних узлах  больше B, мы снова расщепляем результат объединения.&lt;br /&gt;
В процессе повторного расщепления, в случае, если один источник собирает достаточно элементов для того, чтобы полностью заполнить узел, оставшиеся элементы передаются другом источнику. В итоге, если объединённые элементы помещаются в одном узле, в нём освобождается место для ещё одного элемента. Тем самым увеличивается степень использования свободного пространства и откладывается дальнейшее расщепление. В ином случае мы улучшаем распределение элементов в двух ближайших подкластерах.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро алгоритма заключается в многократном выполнении операции вставки нового элемента в дерево, в процессе чего требуется вычисление следующих величин:&lt;br /&gt;
&lt;br /&gt;
* радиуса &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; или диаметра &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластерного элемента. Выполняется при попытке вставить новый элемент в один из подкластеров листьевого узла дерева.&lt;br /&gt;
&lt;br /&gt;
* расстояния между двумя элементами. Выполняется при поиске ближайшего по отношению к новому элементу подкластера в узле дерева по одной из рассмотренных в разд. 1.2.1 метрик &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Зная характеристики кластерных элементов &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;, в результате алгебраических преобразований можно получить следующие упрощенные формулы вычисления необходимых значений:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\vec{X_0} = \frac{\vec{LS}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{SS - 2\vec{X_0}\vec{LS} + N(\vec{X_0})^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{2(N*SS - (\vec{LS})^2)}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{N_1*SS_2 + N_2*SS_1 - 2\vec{LS_1}\vec{LS_2}}{N_1*N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{2((N_1+N_2)(SS_1+SS_2)-(\vec{LS_1}+\vec{LS_2})^2)}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Реализация алгоритма BIRCH состояит из следующих четырёх фаз:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 1&#039;&#039;&#039;. Главной задачей фазы 1 является сканирование всех данных и построение в памяти исходного CF дерева, используя заданное количество памяти. Это дерево стремится отразить информацию о кластеризации данных настолько хорошо, насколько это позволяют ограничения по памяти. При этом плотно распределённые данные группируются в подкластеры, а более разрозненные данные удаляются. После завершения фазы 1 вспомогательные вычисления в дальнейших фазах будут:&lt;br /&gt;
&lt;br /&gt;
1) быстрее, потому что (а) больше не нужны операции ввода-вывода, (b) проблема кластеризации начальных данных упрощается до проблемы кластеризации подкластеров в листьях;&lt;br /&gt;
&lt;br /&gt;
2) точнее, потому что (а) большинство данных с низкой плотностью удалены, (b) оставшиеся данные распределены оптимально (в соответствии с доступным количеством памяти);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 2&#039;&#039;&#039;. Данная фаза является опциональной. Известно, что существующие методы глобальной кластеризации, используемые в рамках фазы 3, имеют различные диапазоны входных значений, при которых их реализация наиболее эффективна. Поэтому потенциально существует пробел между размером фазы 1 и входными значениями фазы 3. И фаза 2 как раз является недостающим связующим звеном: так же как и фаза 1, она сканирует листьевые элементы начального CF дерева для того, чтобы построить меньшее дерево, удаляя ещё больше элементов с низкой плотностью и группируя переполненные подкластеры в большие кластеры.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 3&#039;&#039;&#039;. В данной фазе для листьевых элементов применяется (любой подходящий) алгоритм глобальной кластеризации. Существующие алгоритмы кластеризации наборов точек могут также работать с наборами подкластеров, каждый из которых представлен своим CF вектором. Зная CF вектор, можно вычислить центроид и в дальнейшем заменить всю информацию о кластере этим значением (этого достаточно для вычисления большинства необходимых метрик). После фазы 3 мы получаем набор кластеров, который отражает основные характеристики распределяемых данных.&lt;br /&gt;
Однако, всё ещё могут оставаться некоторые неточности, для устранения которых существует фаза 4.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 4&#039;&#039;&#039;. Данная фаза является опциональной и влечёт за собой затраты на дополнительное сканирование данных для корректировки неточностей и дальнейшего улучшения кластеризации. Фаза 4 использует центроиды кластеров, полученные в фазе 3 для как основы и перераспределяет точки входных данных в ближайшие для них основы для получения нового списка кластеров. Фаза 4, если это необходимо пользователю, может быть расширена дополнительными проходами для уверенности в том, что результат приближается к оптимальному.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Для начала проанализируем вычислительную сложность фазы 1.&lt;br /&gt;
Максимальный размер дерева &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt;. Для того чтобы вставить элемент, мы должны пройти путь от корня до листа (это около &amp;lt;math&amp;gt;1+log_B\frac{M}{P}&amp;lt;/math&amp;gt; узлов). В каждом узле в поисках &amp;quot;ближайшего&amp;quot; нам необходимо просмотреть B элементов; сложность для каждого элемента пропорциональна размерности &#039;&#039;d&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Поэтому сложность вставки всех входных точек &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В случае, когда необходимо перестроить дерево, предположим, что ES - это размер CF элемента. Существует максимум &amp;lt;math&amp;gt;\frac{M}{ES}&amp;lt;/math&amp;gt; листьевых элементов для вставки, поэтому сложность повторной вставки листьевых элементов &amp;lt;math&amp;gt;O(d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Количество итераций перестройки дерева зависит от пороговой величины. На самом деле, это около &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; (двоичное основание появилось из-за того, что мы не можем провести оценку более чем в 2 раза отличающуюся от текущего размера). &amp;lt;math&amp;gt;N_0&amp;lt;/math&amp;gt; - это число входных точек, загруженных в память с пороговым ограничением &amp;lt;math&amp;gt;T_0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Соответственно, итоговая сложность фазы 1 &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P})+log_2\frac{N}{N_0}*d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Анализ фазы 2 проводится аналогично.&lt;br /&gt;
&lt;br /&gt;
Что касается операций ввода-вывода, то в фазе 1 данные сканируются один раз, а в фазе 2 не сканируются вовсе.&lt;br /&gt;
Некоторое количество вычислений связано с удалением точек из областей с низкой плотностью.&lt;br /&gt;
Если количество доступной для этой операции памяти не больше &#039;&#039;M&#039;&#039; и проведено порядка &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; перестроек дерева, то сложность ввода-вывода для фазы 1 существенно не отличается от сложности чтения из файла. Основываясь рассуждениях выше, сложность фаз 1 и 2 будет линейно увеличиваться с ростом N.&lt;br /&gt;
&lt;br /&gt;
В фазе 3 нет операций ввода-вывода. Её сложность ограничена константой, которая зависит от максимального размера входных данных, и варианта выбранного алгоритма для кластеризации. &lt;br /&gt;
&lt;br /&gt;
Фаза 4 снова сканирует данные и записывает каждую точку в подходящий кластер; время работы пропорционально &amp;lt;math&amp;gt;N*K&amp;lt;/math&amp;gt;.   &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Достоинства алгоритма ===&lt;br /&gt;
По сравнению с предыдущими методами BIRCH обладает следующими достоинствами:&lt;br /&gt;
&lt;br /&gt;
1. BIRCH является локальным алгоритмом, то есть каждое решение о каждом элементе кластера принимается без повторного сканирования данных или уже существующих кластеров. Используются только метрики, отражающие близость элементов друг к другу.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH использует факт неравномерного распределения данных в пространстве и поэтому не все данные рассматриваются как одинаково важные для построения кластера. Области с большой плотностью обрабатываются как единый кластер. Данные в более разреженных областях могут удаляться (опционально).&lt;br /&gt;
&lt;br /&gt;
3. BIRCH использует всю доступную память для получения наилучших из возможных подкластеров, в то же время минимизируя затраты на операции ввода/вывода. Оптимизация процесса кластеризации достигается за счет использования взвешенно-сбалансированного дерева. При этом время исполнения линейно.&lt;br /&gt;
&lt;br /&gt;
4. BIRCH не требует всего набора данных заранее (при этом просматривает его всего один раз).&lt;br /&gt;
&lt;br /&gt;
=== Недостатки алгоритма ===&lt;br /&gt;
&lt;br /&gt;
1. Алгоритм позволяет работать только с числовыми данными.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH хорошо выделяет только кластеры сферической формы.&lt;br /&gt;
&lt;br /&gt;
3. Существует необходимость в задании пороговых значений.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* [https://code.google.com/archive/p/jbirch/ Java]&lt;br /&gt;
* [http://scikit-learn.org/stable/modules/generated/sklearn.cluster.Birch.html Python]&lt;br /&gt;
* [http://cucis.ece.northwestern.edu/projects/DMS/MineBench.html#description]&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&lt;br /&gt;
[1] Википедия&lt;/div&gt;</summary>
		<author><name>Светлана Морозова</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13533</id>
		<title>Участник:Smirnov.maxim/BIRCH</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13533"/>
		<updated>2016-10-23T16:34:18Z</updated>

		<summary type="html">&lt;p&gt;Светлана Морозова: /* Макроструктура алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Нахождение полезных для анализа закономерностей в больших объёмах данных с недавних пор вызывает значительный интерес. В связи с этим ввелось и стало активно развиваться такое понятие как &#039;&#039;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7 кластеризация]&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Ранние работы и алгоритмы, разработанные в этой области, не уделяли достаточного внимания анализу очень больших наборов данных или минимизации издержек на процессы ввода-вывода.&lt;br /&gt;
Решением этих проблем стал алгоритм, известный как BIRCH.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIRCH&#039;&#039;&#039; (balanced iterative reducing and clustering using hierarchies)- алгоритм, применяемый в области [https://ru.wikipedia.org/wiki/Data_mining Data mining] и использующий принципы [https://ru.wikipedia.org/wiki/%D0%98%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F иерархической кластеризации].&lt;br /&gt;
&lt;br /&gt;
Если имеется очень большой набор данных, то в пространстве он распределен, как правило, неравномерно. Кластерный анализ определяет места наибольшего и наименьшего скоплений, чтобы таким образом понять всю картину целиком. Кроме того, полученные кластеры визуализируются гораздо нагляднее, чем начальные &amp;quot;сырые&amp;quot; данные.&lt;br /&gt;
Задачей алгоритмов кластеризации является не только простое разбиение данных на кластеры, но и работа в рамках ограниченного объёма доступной памяти (как правило, её объём гораздо меньше, чем размер исходного набора данных) и минимизация времени, требуемого на операции ввода-вывода.&lt;br /&gt;
&lt;br /&gt;
Для наилучшего решения этих проблем BIRCH распределяет входящие данные по кластерам динамически. Для эффективной кластеризации алгоритму требуется всего одно сканирование данных (т.е. с увеличением количества данных сложность увеличивается линейно). А при помощи одной (или более) дополнительных итераций можно и далее улучшать эффективность. BIRCH также является первым алгоритмом, предложенным для эффективного управления &amp;quot;шумами&amp;quot; (данными, которые не вписываются в общее представление модели).&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Теоретическая основа ===&lt;br /&gt;
&lt;br /&gt;
Пусть в кластере имеются &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}, i=1,2,...,N&amp;lt;/math&amp;gt;.&lt;br /&gt;
Тогда &#039;&#039;&#039;центроид&#039;&#039;&#039; &amp;lt;math&amp;gt;{\vec{{X_0}}}&amp;lt;/math&amp;gt;, &#039;&#039;&#039;радиус&#039;&#039;&#039; &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &#039;&#039;&#039;диаметр&#039;&#039;&#039; &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластера определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;{\vec{X_0}}=\frac{\sum_{i=1}^N\vec{X_i}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{\sum_{i=1}^N{(\vec{X_i} - \vec{X_0})}^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{\sum_{i=1}^N\sum_{j=1}^N{(\vec{X_i} - \vec{X_j})}^2}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; - это среднее расстояние от каждой точки до центроида. &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; - это среднее расстояние между парами в кластере. Данные величины являются альтернативными метриками плотности кластера относительно центроида.&lt;br /&gt;
&lt;br /&gt;
Для измерения близости друг к другу двух кластеров вводятся следующие метрики:&lt;br /&gt;
&lt;br /&gt;
пусть даны центроиды двух кластеров &amp;lt;math&amp;gt;\vec{X_{01}}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\vec{X_{02}}&amp;lt;/math&amp;gt;.&lt;br /&gt;
Евклидова метрика &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt; и метрика Манхэттена &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt; между двумя кластерами определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_0 = ((\vec{X_{01}}-\vec{X_{02}})^2)^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_1 = |\vec{X_{01}}-\vec{X_{02}}| = \sum_{i=1}^d |{\vec{X_{01}}}^{(i)}-{\vec{X_{02}}}^{(i)}| &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть имеются два кластера, содержащих соответственно  &amp;lt;math&amp;gt;N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;N_2&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i= 1,2, ...,N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\{\vec{X_j}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j= N_1+1,N_1+2, ...,N_1+N_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Среднее расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &#039;&#039;&#039;среднее внутрикластерное расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &#039;&#039;&#039;дисперсия&#039;&#039;&#039; &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; для двух кластеров определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{\sum_{i=1}^{N_1}\sum_{j=N_1+1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{N_1N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{\sum_{i=1}^{N_1+N_2}\sum_{j=1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_4 = \sum_{k=1}^{N_1+N_2}(\vec{X_k} - \frac{\sum_{i=1}^{N_1+N_2}\vec{X_i}}{N_1+N_2})^2 - \sum_{i=1}^{N_1}(\vec{X_i} - \frac{\sum_{i=1}^{N_1}\vec{X_i}}{N_1})^2 - \sum_{j=N_1+1}^{N_1+N_2}(\vec{X_j} - \frac{\sum_{i=N_1+1}^{N_1+N_2}\vec{X_i}}{N_2})^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Таким образом, величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; относятся к отдельным кластерам, а &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; - к объединению двух кластеров.&lt;br /&gt;
&lt;br /&gt;
=== Кластерный элемент и кластерное дерево ===&lt;br /&gt;
&lt;br /&gt;
В основе концепции алгоритма BIRCH лежат понятия &#039;&#039;&#039;кластерного элемента&#039;&#039;&#039; и &#039;&#039;&#039;кластерного дерева (CF Tree)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====Кластерный элемент ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; Пусть в кластере содержатся  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности  &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;:&amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;i=1,2,...,N&amp;lt;/math&amp;gt;. &lt;br /&gt;
&#039;&#039;&#039;Кластерный элемент (CF)&#039;&#039;&#039; - тройка чисел, характеризующая информацию о кластере: &lt;br /&gt;
&amp;lt;math&amp;gt;CF = (N, \vec{LS}, SS)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - количество элементов входных данных, содержащихся в кластере, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; - линейная сумма входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}\vec{X_i}&amp;lt;/math&amp;gt;), &amp;lt;math&amp;gt;SS&amp;lt;/math&amp;gt; - сумма квадратов входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}{\vec{X_i}}^2&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Теорема&#039;&#039;&#039; Пусть &amp;lt;math&amp;gt;CF_1 = (N_1, \vec{LS_1}, SS_1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;CF_2 = (N_1, \vec{LS_2}, SS_2)&amp;lt;/math&amp;gt; - CF векторы двух непересекающихся кластеров. Тогда при их объединении образуется кластер со следующим CF вектором: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF = CF_1 + CF_2 = (N_1+N_2, \vec{LS_1}+\vec{LS_2}, SS_1+SS_2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Из указанных выше определения и теоремы вытекает тот факт, что при объединении кластеров их CF вектор может вычисляться инкрементно и точно. &lt;br /&gt;
Легко показать, что вычислить величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;, как и обычные метрики, также не составит труда.&lt;br /&gt;
&lt;br /&gt;
Таким образом, в данном случае информацией о кластере является не весь набор точек, а вектор CF. Хранение одного только вектора может показаться неэффективным, но этого вполне достаточно для оперирования всеми необходимыми метриками, на основе которых принимаются решения в алгоритме BIRCH.&lt;br /&gt;
&lt;br /&gt;
==== Кластерное дерево ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; &#039;&#039;&#039;Кластерное дерево (CF Tree)&#039;&#039;&#039; - это взвешенно сбалансированное дерево с двумя параметрами: &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - коэффициент разветвления, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - пороговая величина. Каждый нелистьевой узел дерева имеет не более чем &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; вхождений узлов следующей формы: &amp;lt;math&amp;gt;[CF_i,child_i]&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i=1,2,...,B&amp;lt;/math&amp;gt;, &#039;&#039;child&#039;&#039; - указатель на i-й дочерний узел, &amp;lt;math&amp;gt;CF_i&amp;lt;/math&amp;gt; - CF вектор соответствующего подкластера.&lt;br /&gt;
&lt;br /&gt;
Каждый листьевой узел имеет ссылку на два соседних узла (&#039;&#039;prev&#039;&#039; и &#039;&#039;next&#039;&#039;) для того, чтобы связать все узлы для эффективного сканирования.&lt;br /&gt;
Все листьевые узлы должны удовлетворять пороговому ограничению &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, т.е. диаметр (радиус) не должен превосходить &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;.&lt;br /&gt;
В процессе вставки новых данных CF дерево строится динамически. Оно использует вставку данных для кластеризации точно также как &amp;lt;math&amp;gt;B+&amp;lt;/math&amp;gt; [https://ru.wikipedia.org/wiki/B%2B-%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE дерево] использует её для поиска.&lt;br /&gt;
CF дерево очень компактно, поскольку каждый листьевой узел - это не просто точка, а подкластер (который объединяет множество точек с учётом ограничения &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Операция вставки в &#039;&#039;&#039;CF&#039;&#039;&#039; дерево ====&lt;br /&gt;
&lt;br /&gt;
Опишем алгоритм вставки элемнта &amp;lt;math&amp;gt;Ent&amp;lt;/math&amp;gt; в CF дерево:&lt;br /&gt;
&lt;br /&gt;
1) &#039;&#039;Определение подходящего листа&#039;&#039;: Начиная с корня, алгоритм рекурсивно спускается по CF дереву, выбирая &#039;&#039;&#039;ближайший&#039;&#039;&#039; дочерний узел в соответствии с выбранной метрикой &amp;lt;math&amp;gt;D0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D4&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &#039;&#039;Преобразование листа&#039;&#039;: Когда алгоритм доходит до листа, он находит ближайшую листьевой элемент, скажем, &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;, а затем проверяет, можно ли добавить &#039;&#039;Ent&#039;&#039; к &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt; без нарушения порогового условия. Если да, то с учётом этого изменяется CF вектор для &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;; если нет, то &#039;&#039;Ent&#039;&#039; становится новым элементом листа. Если в листе для этого достаточно места, то шаг окончен, иначе он должен &amp;quot;расщепиться&amp;quot;. Расщепление узла производится при помощи выбора за основу наиболее удалённой друг от друга пары элементов и перераспределение оставшихся элементов в соответствии с выбранным критерием близости.&lt;br /&gt;
&lt;br /&gt;
3) &#039;&#039;Преобразование пути к листу&#039;&#039;: После вставки &#039;&#039;Ent&#039;&#039; в лист мы должны обновить информацию о CF для каждого нелистьевого элемента на пути к листу. При отсутствии расщепления это означает простое сложение CF векторов для отражения факта добавления &#039;&#039;Ent&#039;&#039;. Расщепление листа же требует вставки нового нелистьевого элемента в родительский узел для задания только что созданного листа. Если у родителя есть место для этого элемента, то необходимо просто преобразовать CF векторы на всех более высоких уровнях. В общем случае, однако, нам также придётся расщепить родительский узел, и так далее до корня. Если расщеплён корень, то высота дерева увеличивается на единицу.&lt;br /&gt;
&lt;br /&gt;
4) &#039;&#039;Улучшение слияния&#039;&#039;: Расщепление вызвано ограничением на размер узла, который не зависит от кластеризационных свойств данных. Если во входящем потоке присутствуют &amp;quot;искажённые&amp;quot; (из областей с низкой плотностью) данные, это может повлиять на качество кластеризации, а также уменьшить эффективность использования памяти. Дополнительный шаг алгоритма помогает решить эти проблемы: предположим, что произошло расщепление листа, и распространение этого процесса остановилось на некотором нелистьевом узле &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt;, то есть &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; может вместить дополнительный элемент, полученный после расщепления. Теперь мы сканируем узел &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; для нахождения двух наиболее близких элементов. Если это не пара, отвечающая расщеплению, мы пытаемся объединить их и поставить в соответствие два дочерних узла. Если количество элементов в дочерних узлах  больше B, мы снова расщепляем результат объединения.&lt;br /&gt;
В процессе повторного расщепления, в случае, если один источник собирает достаточно элементов для того, чтобы полностью заполнить узел, оставшиеся элементы передаются другом источнику. В итоге, если объединённые элементы помещаются в одном узле, в нём освобождается место для ещё одного элемента. Тем самым увеличивается степень использования свободного пространства и откладывается дальнейшее расщепление. В ином случае мы улучшаем распределение элементов в двух ближайших подкластерах.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро алгоритма заключается в многократном выполнении операции вставки нового элемента в дерево, в процессе чего требуется вычисление следующих величин:&lt;br /&gt;
&lt;br /&gt;
* радиуса &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; или диаметра &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластерного элемента. Выполняется при попытке вставить новый элемент в один из подкластеров листьевого узла дерева.&lt;br /&gt;
&lt;br /&gt;
* расстояния между двумя элементами. Выполняется при поиске ближайшего по отношению к новому элементу подкластера в узле дерева по одной из рассмотренных в разд. 1.2.1 метрик &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Зная характеристики кластерных элементов &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;, в результате алгебраических преобразований можно получить следующие упрощенные формулы вычисления необходимых значений:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\vec{X_0} = \frac{\vec{LS}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{SS - 2\vec{X_0}\vec{LS} + N(\vec{X_0})^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{2(N*SS - (\vec{LS})^2)}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{N_1*SS_2 + N_2*SS_1 - 2\vec{LS_1}\vec{LS_2}}{N_1*N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{2((N_1+N_2)(SS_1+SS_2)-(\vec{LS_1}+\vec{LS_2})^2)}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Реализация алгоритма BIRCH состояит из следующих четырёх фаз:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 1&#039;&#039;&#039;. Главной задачей фазы 1 является сканирование всех данных и построение в памяти исходного CF дерева, используя заданное количество памяти. Это дерево стремится отразить информацию о кластеризации данных настолько хорошо, насколько это позволяют ограничения по памяти. При этом плотно распределённые данные группируются в подкластеры, а более разрозненные данные удаляются. После завершения фазы 1 вспомогательные вычисления в дальнейших фазах будут:&lt;br /&gt;
&lt;br /&gt;
      1) быстрее, потому что (а) больше не нужны операции ввода-вывода, (b) проблема кластеризации начальных данных упрощается до проблемы кластеризации подкластеров в листьях;&lt;br /&gt;
&lt;br /&gt;
      2) точнее, потому что (а) большинство данных с низкой плотностью удалены, (b) оставшиеся данные распределены оптимально (в соответствии с доступным количеством памяти);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 2&#039;&#039;&#039;. Данная фаза является опциональной. Известно, что существующие методы глобальной кластеризации, используемые в рамках фазы 3, имеют различные диапазоны входных значений, при которых их реализация наиболее эффективна. Поэтому потенциально существует пробел между размером фазы 1 и входными значениями фазы 3. И фаза 2 как раз является недостающим связующим звеном: так же как и фаза 1, она сканирует листьевые элементы начального CF дерева для того, чтобы построить меньшее дерево, удаляя ещё больше элементов с низкой плотностью и группируя переполненные подкластеры в большие кластеры.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 3&#039;&#039;&#039;. В данной фазе для листьевых элементов применяется (любой подходящий) алгоритм глобальной кластеризации. Существующие алгоритмы кластеризации наборов точек могут также работать с наборами подкластеров, каждый из которых представлен своим CF вектором. Зная CF вектор, можно вычислить центроид и в дальнейшем заменить всю информацию о кластере этим значением (этого достаточно для вычисления большинства необходимых метрик). После фазы 3 мы получаем набор кластеров, который отражает основные характеристики распределяемых данных.&lt;br /&gt;
Однако, всё ещё могут оставаться некоторые неточности, для устранения которых существует фаза 4.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 4&#039;&#039;&#039;. Данная фаза является опциональной и влечёт за собой затраты на дополнительное сканирование данных для корректировки неточностей и дальнейшего улучшения кластеризации. Фаза 4 использует центроиды кластеров, полученные в фазе 3 для как основы и перераспределяет точки входных данных в ближайшие для них основы для получения нового списка кластеров. Фаза 4, если это необходимо пользователю, может быть расширена дополнительными проходами для уверенности в том, что результат приближается к оптимальному.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Для начала проанализируем вычислительную сложность фазы 1.&lt;br /&gt;
Максимальный размер дерева &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt;. Для того чтобы вставить элемент, мы должны пройти путь от корня до листа (это около &amp;lt;math&amp;gt;1+log_B\frac{M}{P}&amp;lt;/math&amp;gt; узлов). В каждом узле в поисках &amp;quot;ближайшего&amp;quot; нам необходимо просмотреть B элементов; сложность для каждого элемента пропорциональна размерности &#039;&#039;d&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Поэтому сложность вставки всех входных точек &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В случае, когда необходимо перестроить дерево, предположим, что ES - это размер CF элемента. Существует максимум &amp;lt;math&amp;gt;\frac{M}{ES}&amp;lt;/math&amp;gt; листьевых элементов для вставки, поэтому сложность повторной вставки листьевых элементов &amp;lt;math&amp;gt;O(d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Количество итераций перестройки дерева зависит от пороговой величины. На самом деле, это около &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; (двоичное основание появилось из-за того, что мы не можем провести оценку более чем в 2 раза отличающуюся от текущего размера). &amp;lt;math&amp;gt;N_0&amp;lt;/math&amp;gt; - это число входных точек, загруженных в память с пороговым ограничением &amp;lt;math&amp;gt;T_0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Соответственно, итоговая сложность фазы 1 &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P})+log_2\frac{N}{N_0}*d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Анализ фазы 2 проводится аналогично.&lt;br /&gt;
&lt;br /&gt;
Что касается операций ввода-вывода, то в фазе 1 данные сканируются один раз, а в фазе 2 не сканируются вовсе.&lt;br /&gt;
Некоторое количество вычислений связано с удалением точек из областей с низкой плотностью.&lt;br /&gt;
Если количество доступной для этой операции памяти не больше &#039;&#039;M&#039;&#039; и проведено порядка &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; перестроек дерева, то сложность ввода-вывода для фазы 1 существенно не отличается от сложности чтения из файла. Основываясь рассуждениях выше, сложность фаз 1 и 2 будет линейно увеличиваться с ростом N.&lt;br /&gt;
&lt;br /&gt;
В фазе 3 нет операций ввода-вывода. Её сложность ограничена константой, которая зависит от максимального размера входных данных, и варианта выбранного алгоритма для кластеризации. &lt;br /&gt;
&lt;br /&gt;
Фаза 4 снова сканирует данные и записывает каждую точку в подходящий кластер; время работы пропорционально &amp;lt;math&amp;gt;N*K&amp;lt;/math&amp;gt;.   &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Достоинства алгоритма ===&lt;br /&gt;
По сравнению с предыдущими методами BIRCH обладает следующими достоинствами:&lt;br /&gt;
&lt;br /&gt;
1. BIRCH является локальным алгоритмом, то есть каждое решение о каждом элементе кластера принимается без повторного сканирования данных или уже существующих кластеров. Используются только метрики, отражающие близость элементов друг к другу.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH использует факт неравномерного распределения данных в пространстве и поэтому не все данные рассматриваются как одинаково важные для построения кластера. Области с большой плотностью обрабатываются как единый кластер. Данные в более разреженных областях могут удаляться (опционально).&lt;br /&gt;
&lt;br /&gt;
3. BIRCH использует всю доступную память для получения наилучших из возможных подкластеров, в то же время минимизируя затраты на операции ввода/вывода. Оптимизация процесса кластеризации достигается за счет использования взвешенно-сбалансированного дерева. При этом время исполнения линейно.&lt;br /&gt;
&lt;br /&gt;
4. BIRCH не требует всего набора данных заранее (при этом просматривает его всего один раз).&lt;br /&gt;
&lt;br /&gt;
=== Недостатки алгоритма ===&lt;br /&gt;
&lt;br /&gt;
1. Алгоритм позволяет работать только с числовыми данными.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH хорошо выделяет только кластеры сферической формы.&lt;br /&gt;
&lt;br /&gt;
3. Существует необходимость в задании пороговых значений.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* [https://code.google.com/archive/p/jbirch/ Java]&lt;br /&gt;
* [http://scikit-learn.org/stable/modules/generated/sklearn.cluster.Birch.html Python]&lt;br /&gt;
* [http://cucis.ece.northwestern.edu/projects/DMS/MineBench.html#description]&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&lt;br /&gt;
[1] Википедия&lt;/div&gt;</summary>
		<author><name>Светлана Морозова</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13532</id>
		<title>Участник:Smirnov.maxim/BIRCH</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13532"/>
		<updated>2016-10-23T16:33:50Z</updated>

		<summary type="html">&lt;p&gt;Светлана Морозова: /* Макроструктура алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Нахождение полезных для анализа закономерностей в больших объёмах данных с недавних пор вызывает значительный интерес. В связи с этим ввелось и стало активно развиваться такое понятие как &#039;&#039;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7 кластеризация]&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Ранние работы и алгоритмы, разработанные в этой области, не уделяли достаточного внимания анализу очень больших наборов данных или минимизации издержек на процессы ввода-вывода.&lt;br /&gt;
Решением этих проблем стал алгоритм, известный как BIRCH.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIRCH&#039;&#039;&#039; (balanced iterative reducing and clustering using hierarchies)- алгоритм, применяемый в области [https://ru.wikipedia.org/wiki/Data_mining Data mining] и использующий принципы [https://ru.wikipedia.org/wiki/%D0%98%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F иерархической кластеризации].&lt;br /&gt;
&lt;br /&gt;
Если имеется очень большой набор данных, то в пространстве он распределен, как правило, неравномерно. Кластерный анализ определяет места наибольшего и наименьшего скоплений, чтобы таким образом понять всю картину целиком. Кроме того, полученные кластеры визуализируются гораздо нагляднее, чем начальные &amp;quot;сырые&amp;quot; данные.&lt;br /&gt;
Задачей алгоритмов кластеризации является не только простое разбиение данных на кластеры, но и работа в рамках ограниченного объёма доступной памяти (как правило, её объём гораздо меньше, чем размер исходного набора данных) и минимизация времени, требуемого на операции ввода-вывода.&lt;br /&gt;
&lt;br /&gt;
Для наилучшего решения этих проблем BIRCH распределяет входящие данные по кластерам динамически. Для эффективной кластеризации алгоритму требуется всего одно сканирование данных (т.е. с увеличением количества данных сложность увеличивается линейно). А при помощи одной (или более) дополнительных итераций можно и далее улучшать эффективность. BIRCH также является первым алгоритмом, предложенным для эффективного управления &amp;quot;шумами&amp;quot; (данными, которые не вписываются в общее представление модели).&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Теоретическая основа ===&lt;br /&gt;
&lt;br /&gt;
Пусть в кластере имеются &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}, i=1,2,...,N&amp;lt;/math&amp;gt;.&lt;br /&gt;
Тогда &#039;&#039;&#039;центроид&#039;&#039;&#039; &amp;lt;math&amp;gt;{\vec{{X_0}}}&amp;lt;/math&amp;gt;, &#039;&#039;&#039;радиус&#039;&#039;&#039; &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &#039;&#039;&#039;диаметр&#039;&#039;&#039; &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластера определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;{\vec{X_0}}=\frac{\sum_{i=1}^N\vec{X_i}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{\sum_{i=1}^N{(\vec{X_i} - \vec{X_0})}^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{\sum_{i=1}^N\sum_{j=1}^N{(\vec{X_i} - \vec{X_j})}^2}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; - это среднее расстояние от каждой точки до центроида. &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; - это среднее расстояние между парами в кластере. Данные величины являются альтернативными метриками плотности кластера относительно центроида.&lt;br /&gt;
&lt;br /&gt;
Для измерения близости друг к другу двух кластеров вводятся следующие метрики:&lt;br /&gt;
&lt;br /&gt;
пусть даны центроиды двух кластеров &amp;lt;math&amp;gt;\vec{X_{01}}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\vec{X_{02}}&amp;lt;/math&amp;gt;.&lt;br /&gt;
Евклидова метрика &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt; и метрика Манхэттена &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt; между двумя кластерами определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_0 = ((\vec{X_{01}}-\vec{X_{02}})^2)^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_1 = |\vec{X_{01}}-\vec{X_{02}}| = \sum_{i=1}^d |{\vec{X_{01}}}^{(i)}-{\vec{X_{02}}}^{(i)}| &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть имеются два кластера, содержащих соответственно  &amp;lt;math&amp;gt;N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;N_2&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i= 1,2, ...,N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\{\vec{X_j}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j= N_1+1,N_1+2, ...,N_1+N_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Среднее расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &#039;&#039;&#039;среднее внутрикластерное расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &#039;&#039;&#039;дисперсия&#039;&#039;&#039; &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; для двух кластеров определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{\sum_{i=1}^{N_1}\sum_{j=N_1+1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{N_1N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{\sum_{i=1}^{N_1+N_2}\sum_{j=1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_4 = \sum_{k=1}^{N_1+N_2}(\vec{X_k} - \frac{\sum_{i=1}^{N_1+N_2}\vec{X_i}}{N_1+N_2})^2 - \sum_{i=1}^{N_1}(\vec{X_i} - \frac{\sum_{i=1}^{N_1}\vec{X_i}}{N_1})^2 - \sum_{j=N_1+1}^{N_1+N_2}(\vec{X_j} - \frac{\sum_{i=N_1+1}^{N_1+N_2}\vec{X_i}}{N_2})^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Таким образом, величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; относятся к отдельным кластерам, а &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; - к объединению двух кластеров.&lt;br /&gt;
&lt;br /&gt;
=== Кластерный элемент и кластерное дерево ===&lt;br /&gt;
&lt;br /&gt;
В основе концепции алгоритма BIRCH лежат понятия &#039;&#039;&#039;кластерного элемента&#039;&#039;&#039; и &#039;&#039;&#039;кластерного дерева (CF Tree)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====Кластерный элемент ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; Пусть в кластере содержатся  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности  &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;:&amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;i=1,2,...,N&amp;lt;/math&amp;gt;. &lt;br /&gt;
&#039;&#039;&#039;Кластерный элемент (CF)&#039;&#039;&#039; - тройка чисел, характеризующая информацию о кластере: &lt;br /&gt;
&amp;lt;math&amp;gt;CF = (N, \vec{LS}, SS)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - количество элементов входных данных, содержащихся в кластере, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; - линейная сумма входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}\vec{X_i}&amp;lt;/math&amp;gt;), &amp;lt;math&amp;gt;SS&amp;lt;/math&amp;gt; - сумма квадратов входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}{\vec{X_i}}^2&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Теорема&#039;&#039;&#039; Пусть &amp;lt;math&amp;gt;CF_1 = (N_1, \vec{LS_1}, SS_1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;CF_2 = (N_1, \vec{LS_2}, SS_2)&amp;lt;/math&amp;gt; - CF векторы двух непересекающихся кластеров. Тогда при их объединении образуется кластер со следующим CF вектором: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF = CF_1 + CF_2 = (N_1+N_2, \vec{LS_1}+\vec{LS_2}, SS_1+SS_2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Из указанных выше определения и теоремы вытекает тот факт, что при объединении кластеров их CF вектор может вычисляться инкрементно и точно. &lt;br /&gt;
Легко показать, что вычислить величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;, как и обычные метрики, также не составит труда.&lt;br /&gt;
&lt;br /&gt;
Таким образом, в данном случае информацией о кластере является не весь набор точек, а вектор CF. Хранение одного только вектора может показаться неэффективным, но этого вполне достаточно для оперирования всеми необходимыми метриками, на основе которых принимаются решения в алгоритме BIRCH.&lt;br /&gt;
&lt;br /&gt;
==== Кластерное дерево ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; &#039;&#039;&#039;Кластерное дерево (CF Tree)&#039;&#039;&#039; - это взвешенно сбалансированное дерево с двумя параметрами: &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - коэффициент разветвления, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - пороговая величина. Каждый нелистьевой узел дерева имеет не более чем &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; вхождений узлов следующей формы: &amp;lt;math&amp;gt;[CF_i,child_i]&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i=1,2,...,B&amp;lt;/math&amp;gt;, &#039;&#039;child&#039;&#039; - указатель на i-й дочерний узел, &amp;lt;math&amp;gt;CF_i&amp;lt;/math&amp;gt; - CF вектор соответствующего подкластера.&lt;br /&gt;
&lt;br /&gt;
Каждый листьевой узел имеет ссылку на два соседних узла (&#039;&#039;prev&#039;&#039; и &#039;&#039;next&#039;&#039;) для того, чтобы связать все узлы для эффективного сканирования.&lt;br /&gt;
Все листьевые узлы должны удовлетворять пороговому ограничению &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, т.е. диаметр (радиус) не должен превосходить &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;.&lt;br /&gt;
В процессе вставки новых данных CF дерево строится динамически. Оно использует вставку данных для кластеризации точно также как &amp;lt;math&amp;gt;B+&amp;lt;/math&amp;gt; [https://ru.wikipedia.org/wiki/B%2B-%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE дерево] использует её для поиска.&lt;br /&gt;
CF дерево очень компактно, поскольку каждый листьевой узел - это не просто точка, а подкластер (который объединяет множество точек с учётом ограничения &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Операция вставки в &#039;&#039;&#039;CF&#039;&#039;&#039; дерево ====&lt;br /&gt;
&lt;br /&gt;
Опишем алгоритм вставки элемнта &amp;lt;math&amp;gt;Ent&amp;lt;/math&amp;gt; в CF дерево:&lt;br /&gt;
&lt;br /&gt;
1) &#039;&#039;Определение подходящего листа&#039;&#039;: Начиная с корня, алгоритм рекурсивно спускается по CF дереву, выбирая &#039;&#039;&#039;ближайший&#039;&#039;&#039; дочерний узел в соответствии с выбранной метрикой &amp;lt;math&amp;gt;D0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D4&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &#039;&#039;Преобразование листа&#039;&#039;: Когда алгоритм доходит до листа, он находит ближайшую листьевой элемент, скажем, &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;, а затем проверяет, можно ли добавить &#039;&#039;Ent&#039;&#039; к &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt; без нарушения порогового условия. Если да, то с учётом этого изменяется CF вектор для &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;; если нет, то &#039;&#039;Ent&#039;&#039; становится новым элементом листа. Если в листе для этого достаточно места, то шаг окончен, иначе он должен &amp;quot;расщепиться&amp;quot;. Расщепление узла производится при помощи выбора за основу наиболее удалённой друг от друга пары элементов и перераспределение оставшихся элементов в соответствии с выбранным критерием близости.&lt;br /&gt;
&lt;br /&gt;
3) &#039;&#039;Преобразование пути к листу&#039;&#039;: После вставки &#039;&#039;Ent&#039;&#039; в лист мы должны обновить информацию о CF для каждого нелистьевого элемента на пути к листу. При отсутствии расщепления это означает простое сложение CF векторов для отражения факта добавления &#039;&#039;Ent&#039;&#039;. Расщепление листа же требует вставки нового нелистьевого элемента в родительский узел для задания только что созданного листа. Если у родителя есть место для этого элемента, то необходимо просто преобразовать CF векторы на всех более высоких уровнях. В общем случае, однако, нам также придётся расщепить родительский узел, и так далее до корня. Если расщеплён корень, то высота дерева увеличивается на единицу.&lt;br /&gt;
&lt;br /&gt;
4) &#039;&#039;Улучшение слияния&#039;&#039;: Расщепление вызвано ограничением на размер узла, который не зависит от кластеризационных свойств данных. Если во входящем потоке присутствуют &amp;quot;искажённые&amp;quot; (из областей с низкой плотностью) данные, это может повлиять на качество кластеризации, а также уменьшить эффективность использования памяти. Дополнительный шаг алгоритма помогает решить эти проблемы: предположим, что произошло расщепление листа, и распространение этого процесса остановилось на некотором нелистьевом узле &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt;, то есть &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; может вместить дополнительный элемент, полученный после расщепления. Теперь мы сканируем узел &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; для нахождения двух наиболее близких элементов. Если это не пара, отвечающая расщеплению, мы пытаемся объединить их и поставить в соответствие два дочерних узла. Если количество элементов в дочерних узлах  больше B, мы снова расщепляем результат объединения.&lt;br /&gt;
В процессе повторного расщепления, в случае, если один источник собирает достаточно элементов для того, чтобы полностью заполнить узел, оставшиеся элементы передаются другом источнику. В итоге, если объединённые элементы помещаются в одном узле, в нём освобождается место для ещё одного элемента. Тем самым увеличивается степень использования свободного пространства и откладывается дальнейшее расщепление. В ином случае мы улучшаем распределение элементов в двух ближайших подкластерах.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро алгоритма заключается в многократном выполнении операции вставки нового элемента в дерево, в процессе чего требуется вычисление следующих величин:&lt;br /&gt;
&lt;br /&gt;
* радиуса &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; или диаметра &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластерного элемента. Выполняется при попытке вставить новый элемент в один из подкластеров листьевого узла дерева.&lt;br /&gt;
&lt;br /&gt;
* расстояния между двумя элементами. Выполняется при поиске ближайшего по отношению к новому элементу подкластера в узле дерева по одной из рассмотренных в разд. 1.2.1 метрик &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Зная характеристики кластерных элементов &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;, в результате алгебраических преобразований можно получить следующие упрощенные формулы вычисления необходимых значений:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\vec{X_0} = \frac{\vec{LS}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{SS - 2\vec{X_0}\vec{LS} + N(\vec{X_0})^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{2(N*SS - (\vec{LS})^2)}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{N_1*SS_2 + N_2*SS_1 - 2\vec{LS_1}\vec{LS_2}}{N_1*N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{2((N_1+N_2)(SS_1+SS_2)-(\vec{LS_1}+\vec{LS_2})^2)}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Реализация алгоритма BIRCH состояит из следующих четырёх фаз:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 1&#039;&#039;&#039;. Главной задачей фазы 1 является сканирование всех данных и построение в памяти исходного CF дерева, используя заданное количество памяти. Это дерево стремится отразить информацию о кластеризации данных настолько хорошо, насколько это позволяют ограничения по памяти. При этом плотно распределённые данные группируются в подкластеры, а более разрозненные данные удаляются. После завершения фазы 1 вспомогательные вычисления в дальнейших фазах будут:&lt;br /&gt;
&lt;br /&gt;
** 1) быстрее, потому что (а) больше не нужны операции ввода-вывода, (b) проблема кластеризации начальных данных упрощается до проблемы кластеризации подкластеров в листьях;&lt;br /&gt;
&lt;br /&gt;
** 2) точнее, потому что (а) большинство данных с низкой плотностью удалены, (b) оставшиеся данные распределены оптимально (в соответствии с доступным количеством памяти);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 2&#039;&#039;&#039;. Данная фаза является опциональной. Известно, что существующие методы глобальной кластеризации, используемые в рамках фазы 3, имеют различные диапазоны входных значений, при которых их реализация наиболее эффективна. Поэтому потенциально существует пробел между размером фазы 1 и входными значениями фазы 3. И фаза 2 как раз является недостающим связующим звеном: так же как и фаза 1, она сканирует листьевые элементы начального CF дерева для того, чтобы построить меньшее дерево, удаляя ещё больше элементов с низкой плотностью и группируя переполненные подкластеры в большие кластеры.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 3&#039;&#039;&#039;. В данной фазе для листьевых элементов применяется (любой подходящий) алгоритм глобальной кластеризации. Существующие алгоритмы кластеризации наборов точек могут также работать с наборами подкластеров, каждый из которых представлен своим CF вектором. Зная CF вектор, можно вычислить центроид и в дальнейшем заменить всю информацию о кластере этим значением (этого достаточно для вычисления большинства необходимых метрик). После фазы 3 мы получаем набор кластеров, который отражает основные характеристики распределяемых данных.&lt;br /&gt;
Однако, всё ещё могут оставаться некоторые неточности, для устранения которых существует фаза 4.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 4&#039;&#039;&#039;. Данная фаза является опциональной и влечёт за собой затраты на дополнительное сканирование данных для корректировки неточностей и дальнейшего улучшения кластеризации. Фаза 4 использует центроиды кластеров, полученные в фазе 3 для как основы и перераспределяет точки входных данных в ближайшие для них основы для получения нового списка кластеров. Фаза 4, если это необходимо пользователю, может быть расширена дополнительными проходами для уверенности в том, что результат приближается к оптимальному.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Для начала проанализируем вычислительную сложность фазы 1.&lt;br /&gt;
Максимальный размер дерева &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt;. Для того чтобы вставить элемент, мы должны пройти путь от корня до листа (это около &amp;lt;math&amp;gt;1+log_B\frac{M}{P}&amp;lt;/math&amp;gt; узлов). В каждом узле в поисках &amp;quot;ближайшего&amp;quot; нам необходимо просмотреть B элементов; сложность для каждого элемента пропорциональна размерности &#039;&#039;d&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Поэтому сложность вставки всех входных точек &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В случае, когда необходимо перестроить дерево, предположим, что ES - это размер CF элемента. Существует максимум &amp;lt;math&amp;gt;\frac{M}{ES}&amp;lt;/math&amp;gt; листьевых элементов для вставки, поэтому сложность повторной вставки листьевых элементов &amp;lt;math&amp;gt;O(d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Количество итераций перестройки дерева зависит от пороговой величины. На самом деле, это около &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; (двоичное основание появилось из-за того, что мы не можем провести оценку более чем в 2 раза отличающуюся от текущего размера). &amp;lt;math&amp;gt;N_0&amp;lt;/math&amp;gt; - это число входных точек, загруженных в память с пороговым ограничением &amp;lt;math&amp;gt;T_0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Соответственно, итоговая сложность фазы 1 &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P})+log_2\frac{N}{N_0}*d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Анализ фазы 2 проводится аналогично.&lt;br /&gt;
&lt;br /&gt;
Что касается операций ввода-вывода, то в фазе 1 данные сканируются один раз, а в фазе 2 не сканируются вовсе.&lt;br /&gt;
Некоторое количество вычислений связано с удалением точек из областей с низкой плотностью.&lt;br /&gt;
Если количество доступной для этой операции памяти не больше &#039;&#039;M&#039;&#039; и проведено порядка &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; перестроек дерева, то сложность ввода-вывода для фазы 1 существенно не отличается от сложности чтения из файла. Основываясь рассуждениях выше, сложность фаз 1 и 2 будет линейно увеличиваться с ростом N.&lt;br /&gt;
&lt;br /&gt;
В фазе 3 нет операций ввода-вывода. Её сложность ограничена константой, которая зависит от максимального размера входных данных, и варианта выбранного алгоритма для кластеризации. &lt;br /&gt;
&lt;br /&gt;
Фаза 4 снова сканирует данные и записывает каждую точку в подходящий кластер; время работы пропорционально &amp;lt;math&amp;gt;N*K&amp;lt;/math&amp;gt;.   &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Достоинства алгоритма ===&lt;br /&gt;
По сравнению с предыдущими методами BIRCH обладает следующими достоинствами:&lt;br /&gt;
&lt;br /&gt;
1. BIRCH является локальным алгоритмом, то есть каждое решение о каждом элементе кластера принимается без повторного сканирования данных или уже существующих кластеров. Используются только метрики, отражающие близость элементов друг к другу.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH использует факт неравномерного распределения данных в пространстве и поэтому не все данные рассматриваются как одинаково важные для построения кластера. Области с большой плотностью обрабатываются как единый кластер. Данные в более разреженных областях могут удаляться (опционально).&lt;br /&gt;
&lt;br /&gt;
3. BIRCH использует всю доступную память для получения наилучших из возможных подкластеров, в то же время минимизируя затраты на операции ввода/вывода. Оптимизация процесса кластеризации достигается за счет использования взвешенно-сбалансированного дерева. При этом время исполнения линейно.&lt;br /&gt;
&lt;br /&gt;
4. BIRCH не требует всего набора данных заранее (при этом просматривает его всего один раз).&lt;br /&gt;
&lt;br /&gt;
=== Недостатки алгоритма ===&lt;br /&gt;
&lt;br /&gt;
1. Алгоритм позволяет работать только с числовыми данными.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH хорошо выделяет только кластеры сферической формы.&lt;br /&gt;
&lt;br /&gt;
3. Существует необходимость в задании пороговых значений.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* [https://code.google.com/archive/p/jbirch/ Java]&lt;br /&gt;
* [http://scikit-learn.org/stable/modules/generated/sklearn.cluster.Birch.html Python]&lt;br /&gt;
* [http://cucis.ece.northwestern.edu/projects/DMS/MineBench.html#description]&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&lt;br /&gt;
[1] Википедия&lt;/div&gt;</summary>
		<author><name>Светлана Морозова</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13531</id>
		<title>Участник:Smirnov.maxim/BIRCH</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13531"/>
		<updated>2016-10-23T16:33:14Z</updated>

		<summary type="html">&lt;p&gt;Светлана Морозова: /* Макроструктура алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Нахождение полезных для анализа закономерностей в больших объёмах данных с недавних пор вызывает значительный интерес. В связи с этим ввелось и стало активно развиваться такое понятие как &#039;&#039;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7 кластеризация]&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Ранние работы и алгоритмы, разработанные в этой области, не уделяли достаточного внимания анализу очень больших наборов данных или минимизации издержек на процессы ввода-вывода.&lt;br /&gt;
Решением этих проблем стал алгоритм, известный как BIRCH.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIRCH&#039;&#039;&#039; (balanced iterative reducing and clustering using hierarchies)- алгоритм, применяемый в области [https://ru.wikipedia.org/wiki/Data_mining Data mining] и использующий принципы [https://ru.wikipedia.org/wiki/%D0%98%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F иерархической кластеризации].&lt;br /&gt;
&lt;br /&gt;
Если имеется очень большой набор данных, то в пространстве он распределен, как правило, неравномерно. Кластерный анализ определяет места наибольшего и наименьшего скоплений, чтобы таким образом понять всю картину целиком. Кроме того, полученные кластеры визуализируются гораздо нагляднее, чем начальные &amp;quot;сырые&amp;quot; данные.&lt;br /&gt;
Задачей алгоритмов кластеризации является не только простое разбиение данных на кластеры, но и работа в рамках ограниченного объёма доступной памяти (как правило, её объём гораздо меньше, чем размер исходного набора данных) и минимизация времени, требуемого на операции ввода-вывода.&lt;br /&gt;
&lt;br /&gt;
Для наилучшего решения этих проблем BIRCH распределяет входящие данные по кластерам динамически. Для эффективной кластеризации алгоритму требуется всего одно сканирование данных (т.е. с увеличением количества данных сложность увеличивается линейно). А при помощи одной (или более) дополнительных итераций можно и далее улучшать эффективность. BIRCH также является первым алгоритмом, предложенным для эффективного управления &amp;quot;шумами&amp;quot; (данными, которые не вписываются в общее представление модели).&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Теоретическая основа ===&lt;br /&gt;
&lt;br /&gt;
Пусть в кластере имеются &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}, i=1,2,...,N&amp;lt;/math&amp;gt;.&lt;br /&gt;
Тогда &#039;&#039;&#039;центроид&#039;&#039;&#039; &amp;lt;math&amp;gt;{\vec{{X_0}}}&amp;lt;/math&amp;gt;, &#039;&#039;&#039;радиус&#039;&#039;&#039; &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &#039;&#039;&#039;диаметр&#039;&#039;&#039; &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластера определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;{\vec{X_0}}=\frac{\sum_{i=1}^N\vec{X_i}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{\sum_{i=1}^N{(\vec{X_i} - \vec{X_0})}^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{\sum_{i=1}^N\sum_{j=1}^N{(\vec{X_i} - \vec{X_j})}^2}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; - это среднее расстояние от каждой точки до центроида. &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; - это среднее расстояние между парами в кластере. Данные величины являются альтернативными метриками плотности кластера относительно центроида.&lt;br /&gt;
&lt;br /&gt;
Для измерения близости друг к другу двух кластеров вводятся следующие метрики:&lt;br /&gt;
&lt;br /&gt;
пусть даны центроиды двух кластеров &amp;lt;math&amp;gt;\vec{X_{01}}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\vec{X_{02}}&amp;lt;/math&amp;gt;.&lt;br /&gt;
Евклидова метрика &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt; и метрика Манхэттена &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt; между двумя кластерами определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_0 = ((\vec{X_{01}}-\vec{X_{02}})^2)^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_1 = |\vec{X_{01}}-\vec{X_{02}}| = \sum_{i=1}^d |{\vec{X_{01}}}^{(i)}-{\vec{X_{02}}}^{(i)}| &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть имеются два кластера, содержащих соответственно  &amp;lt;math&amp;gt;N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;N_2&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i= 1,2, ...,N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\{\vec{X_j}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j= N_1+1,N_1+2, ...,N_1+N_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Среднее расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &#039;&#039;&#039;среднее внутрикластерное расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &#039;&#039;&#039;дисперсия&#039;&#039;&#039; &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; для двух кластеров определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{\sum_{i=1}^{N_1}\sum_{j=N_1+1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{N_1N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{\sum_{i=1}^{N_1+N_2}\sum_{j=1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_4 = \sum_{k=1}^{N_1+N_2}(\vec{X_k} - \frac{\sum_{i=1}^{N_1+N_2}\vec{X_i}}{N_1+N_2})^2 - \sum_{i=1}^{N_1}(\vec{X_i} - \frac{\sum_{i=1}^{N_1}\vec{X_i}}{N_1})^2 - \sum_{j=N_1+1}^{N_1+N_2}(\vec{X_j} - \frac{\sum_{i=N_1+1}^{N_1+N_2}\vec{X_i}}{N_2})^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Таким образом, величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; относятся к отдельным кластерам, а &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; - к объединению двух кластеров.&lt;br /&gt;
&lt;br /&gt;
=== Кластерный элемент и кластерное дерево ===&lt;br /&gt;
&lt;br /&gt;
В основе концепции алгоритма BIRCH лежат понятия &#039;&#039;&#039;кластерного элемента&#039;&#039;&#039; и &#039;&#039;&#039;кластерного дерева (CF Tree)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====Кластерный элемент ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; Пусть в кластере содержатся  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности  &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;:&amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;i=1,2,...,N&amp;lt;/math&amp;gt;. &lt;br /&gt;
&#039;&#039;&#039;Кластерный элемент (CF)&#039;&#039;&#039; - тройка чисел, характеризующая информацию о кластере: &lt;br /&gt;
&amp;lt;math&amp;gt;CF = (N, \vec{LS}, SS)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - количество элементов входных данных, содержащихся в кластере, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; - линейная сумма входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}\vec{X_i}&amp;lt;/math&amp;gt;), &amp;lt;math&amp;gt;SS&amp;lt;/math&amp;gt; - сумма квадратов входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}{\vec{X_i}}^2&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Теорема&#039;&#039;&#039; Пусть &amp;lt;math&amp;gt;CF_1 = (N_1, \vec{LS_1}, SS_1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;CF_2 = (N_1, \vec{LS_2}, SS_2)&amp;lt;/math&amp;gt; - CF векторы двух непересекающихся кластеров. Тогда при их объединении образуется кластер со следующим CF вектором: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF = CF_1 + CF_2 = (N_1+N_2, \vec{LS_1}+\vec{LS_2}, SS_1+SS_2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Из указанных выше определения и теоремы вытекает тот факт, что при объединении кластеров их CF вектор может вычисляться инкрементно и точно. &lt;br /&gt;
Легко показать, что вычислить величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;, как и обычные метрики, также не составит труда.&lt;br /&gt;
&lt;br /&gt;
Таким образом, в данном случае информацией о кластере является не весь набор точек, а вектор CF. Хранение одного только вектора может показаться неэффективным, но этого вполне достаточно для оперирования всеми необходимыми метриками, на основе которых принимаются решения в алгоритме BIRCH.&lt;br /&gt;
&lt;br /&gt;
==== Кластерное дерево ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; &#039;&#039;&#039;Кластерное дерево (CF Tree)&#039;&#039;&#039; - это взвешенно сбалансированное дерево с двумя параметрами: &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - коэффициент разветвления, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - пороговая величина. Каждый нелистьевой узел дерева имеет не более чем &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; вхождений узлов следующей формы: &amp;lt;math&amp;gt;[CF_i,child_i]&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i=1,2,...,B&amp;lt;/math&amp;gt;, &#039;&#039;child&#039;&#039; - указатель на i-й дочерний узел, &amp;lt;math&amp;gt;CF_i&amp;lt;/math&amp;gt; - CF вектор соответствующего подкластера.&lt;br /&gt;
&lt;br /&gt;
Каждый листьевой узел имеет ссылку на два соседних узла (&#039;&#039;prev&#039;&#039; и &#039;&#039;next&#039;&#039;) для того, чтобы связать все узлы для эффективного сканирования.&lt;br /&gt;
Все листьевые узлы должны удовлетворять пороговому ограничению &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, т.е. диаметр (радиус) не должен превосходить &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;.&lt;br /&gt;
В процессе вставки новых данных CF дерево строится динамически. Оно использует вставку данных для кластеризации точно также как &amp;lt;math&amp;gt;B+&amp;lt;/math&amp;gt; [https://ru.wikipedia.org/wiki/B%2B-%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE дерево] использует её для поиска.&lt;br /&gt;
CF дерево очень компактно, поскольку каждый листьевой узел - это не просто точка, а подкластер (который объединяет множество точек с учётом ограничения &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Операция вставки в &#039;&#039;&#039;CF&#039;&#039;&#039; дерево ====&lt;br /&gt;
&lt;br /&gt;
Опишем алгоритм вставки элемнта &amp;lt;math&amp;gt;Ent&amp;lt;/math&amp;gt; в CF дерево:&lt;br /&gt;
&lt;br /&gt;
1) &#039;&#039;Определение подходящего листа&#039;&#039;: Начиная с корня, алгоритм рекурсивно спускается по CF дереву, выбирая &#039;&#039;&#039;ближайший&#039;&#039;&#039; дочерний узел в соответствии с выбранной метрикой &amp;lt;math&amp;gt;D0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D4&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &#039;&#039;Преобразование листа&#039;&#039;: Когда алгоритм доходит до листа, он находит ближайшую листьевой элемент, скажем, &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;, а затем проверяет, можно ли добавить &#039;&#039;Ent&#039;&#039; к &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt; без нарушения порогового условия. Если да, то с учётом этого изменяется CF вектор для &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;; если нет, то &#039;&#039;Ent&#039;&#039; становится новым элементом листа. Если в листе для этого достаточно места, то шаг окончен, иначе он должен &amp;quot;расщепиться&amp;quot;. Расщепление узла производится при помощи выбора за основу наиболее удалённой друг от друга пары элементов и перераспределение оставшихся элементов в соответствии с выбранным критерием близости.&lt;br /&gt;
&lt;br /&gt;
3) &#039;&#039;Преобразование пути к листу&#039;&#039;: После вставки &#039;&#039;Ent&#039;&#039; в лист мы должны обновить информацию о CF для каждого нелистьевого элемента на пути к листу. При отсутствии расщепления это означает простое сложение CF векторов для отражения факта добавления &#039;&#039;Ent&#039;&#039;. Расщепление листа же требует вставки нового нелистьевого элемента в родительский узел для задания только что созданного листа. Если у родителя есть место для этого элемента, то необходимо просто преобразовать CF векторы на всех более высоких уровнях. В общем случае, однако, нам также придётся расщепить родительский узел, и так далее до корня. Если расщеплён корень, то высота дерева увеличивается на единицу.&lt;br /&gt;
&lt;br /&gt;
4) &#039;&#039;Улучшение слияния&#039;&#039;: Расщепление вызвано ограничением на размер узла, который не зависит от кластеризационных свойств данных. Если во входящем потоке присутствуют &amp;quot;искажённые&amp;quot; (из областей с низкой плотностью) данные, это может повлиять на качество кластеризации, а также уменьшить эффективность использования памяти. Дополнительный шаг алгоритма помогает решить эти проблемы: предположим, что произошло расщепление листа, и распространение этого процесса остановилось на некотором нелистьевом узле &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt;, то есть &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; может вместить дополнительный элемент, полученный после расщепления. Теперь мы сканируем узел &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; для нахождения двух наиболее близких элементов. Если это не пара, отвечающая расщеплению, мы пытаемся объединить их и поставить в соответствие два дочерних узла. Если количество элементов в дочерних узлах  больше B, мы снова расщепляем результат объединения.&lt;br /&gt;
В процессе повторного расщепления, в случае, если один источник собирает достаточно элементов для того, чтобы полностью заполнить узел, оставшиеся элементы передаются другом источнику. В итоге, если объединённые элементы помещаются в одном узле, в нём освобождается место для ещё одного элемента. Тем самым увеличивается степень использования свободного пространства и откладывается дальнейшее расщепление. В ином случае мы улучшаем распределение элементов в двух ближайших подкластерах.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро алгоритма заключается в многократном выполнении операции вставки нового элемента в дерево, в процессе чего требуется вычисление следующих величин:&lt;br /&gt;
&lt;br /&gt;
* радиуса &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; или диаметра &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластерного элемента. Выполняется при попытке вставить новый элемент в один из подкластеров листьевого узла дерева.&lt;br /&gt;
&lt;br /&gt;
* расстояния между двумя элементами. Выполняется при поиске ближайшего по отношению к новому элементу подкластера в узле дерева по одной из рассмотренных в разд. 1.2.1 метрик &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Зная характеристики кластерных элементов &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;, в результате алгебраических преобразований можно получить следующие упрощенные формулы вычисления необходимых значений:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\vec{X_0} = \frac{\vec{LS}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{SS - 2\vec{X_0}\vec{LS} + N(\vec{X_0})^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{2(N*SS - (\vec{LS})^2)}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{N_1*SS_2 + N_2*SS_1 - 2\vec{LS_1}\vec{LS_2}}{N_1*N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{2((N_1+N_2)(SS_1+SS_2)-(\vec{LS_1}+\vec{LS_2})^2)}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Реализация алгоритма BIRCH состояит из следующих четырёх фаз:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 1&#039;&#039;&#039;. Главной задачей фазы 1 является сканирование всех данных и построение в памяти исходного CF дерева, используя заданное количество памяти. Это дерево стремится отразить информацию о кластеризации данных настолько хорошо, насколько это позволяют ограничения по памяти. При этом плотно распределённые данные группируются в подкластеры, а более разрозненные данные удаляются. После завершения фазы 1 вспомогательные вычисления в дальнейших фазах будут:&lt;br /&gt;
1) быстрее, потому что (а) больше не нужны операции ввода-вывода, (b) проблема кластеризации начальных данных упрощается до проблемы кластеризации подкластеров в листьях;&lt;br /&gt;
2) точнее, потому что (а) большинство данных с низкой плотностью удалены, (b) оставшиеся данные распределены оптимально (в соответствии с доступным количеством памяти);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 2&#039;&#039;&#039;. Данная фаза является опциональной. Известно, что существующие методы глобальной кластеризации, используемые в рамках фазы 3, имеют различные диапазоны входных значений, при которых их реализация наиболее эффективна. Поэтому потенциально существует пробел между размером фазы 1 и входными значениями фазы 3. И фаза 2 как раз является недостающим связующим звеном: так же как и фаза 1, она сканирует листьевые элементы начального CF дерева для того, чтобы построить меньшее дерево, удаляя ещё больше элементов с низкой плотностью и группируя переполненные подкластеры в большие кластеры.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 3&#039;&#039;&#039;. В данной фазе для листьевых элементов применяется (любой подходящий) алгоритм глобальной кластеризации. Существующие алгоритмы кластеризации наборов точек могут также работать с наборами подкластеров, каждый из которых представлен своим CF вектором. Зная CF вектор, можно вычислить центроид и в дальнейшем заменить всю информацию о кластере этим значением (этого достаточно для вычисления большинства необходимых метрик). После фазы 3 мы получаем набор кластеров, который отражает основные характеристики распределяемых данных.&lt;br /&gt;
Однако, всё ещё могут оставаться некоторые неточности, для устранения которых существует фаза 4.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 4&#039;&#039;&#039;. Данная фаза является опциональной и влечёт за собой затраты на дополнительное сканирование данных для корректировки неточностей и дальнейшего улучшения кластеризации. Фаза 4 использует центроиды кластеров, полученные в фазе 3 для как основы и перераспределяет точки входных данных в ближайшие для них основы для получения нового списка кластеров. Фаза 4, если это необходимо пользователю, может быть расширена дополнительными проходами для уверенности в том, что результат приближается к оптимальному.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Для начала проанализируем вычислительную сложность фазы 1.&lt;br /&gt;
Максимальный размер дерева &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt;. Для того чтобы вставить элемент, мы должны пройти путь от корня до листа (это около &amp;lt;math&amp;gt;1+log_B\frac{M}{P}&amp;lt;/math&amp;gt; узлов). В каждом узле в поисках &amp;quot;ближайшего&amp;quot; нам необходимо просмотреть B элементов; сложность для каждого элемента пропорциональна размерности &#039;&#039;d&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Поэтому сложность вставки всех входных точек &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В случае, когда необходимо перестроить дерево, предположим, что ES - это размер CF элемента. Существует максимум &amp;lt;math&amp;gt;\frac{M}{ES}&amp;lt;/math&amp;gt; листьевых элементов для вставки, поэтому сложность повторной вставки листьевых элементов &amp;lt;math&amp;gt;O(d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Количество итераций перестройки дерева зависит от пороговой величины. На самом деле, это около &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; (двоичное основание появилось из-за того, что мы не можем провести оценку более чем в 2 раза отличающуюся от текущего размера). &amp;lt;math&amp;gt;N_0&amp;lt;/math&amp;gt; - это число входных точек, загруженных в память с пороговым ограничением &amp;lt;math&amp;gt;T_0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Соответственно, итоговая сложность фазы 1 &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P})+log_2\frac{N}{N_0}*d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Анализ фазы 2 проводится аналогично.&lt;br /&gt;
&lt;br /&gt;
Что касается операций ввода-вывода, то в фазе 1 данные сканируются один раз, а в фазе 2 не сканируются вовсе.&lt;br /&gt;
Некоторое количество вычислений связано с удалением точек из областей с низкой плотностью.&lt;br /&gt;
Если количество доступной для этой операции памяти не больше &#039;&#039;M&#039;&#039; и проведено порядка &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; перестроек дерева, то сложность ввода-вывода для фазы 1 существенно не отличается от сложности чтения из файла. Основываясь рассуждениях выше, сложность фаз 1 и 2 будет линейно увеличиваться с ростом N.&lt;br /&gt;
&lt;br /&gt;
В фазе 3 нет операций ввода-вывода. Её сложность ограничена константой, которая зависит от максимального размера входных данных, и варианта выбранного алгоритма для кластеризации. &lt;br /&gt;
&lt;br /&gt;
Фаза 4 снова сканирует данные и записывает каждую точку в подходящий кластер; время работы пропорционально &amp;lt;math&amp;gt;N*K&amp;lt;/math&amp;gt;.   &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Достоинства алгоритма ===&lt;br /&gt;
По сравнению с предыдущими методами BIRCH обладает следующими достоинствами:&lt;br /&gt;
&lt;br /&gt;
1. BIRCH является локальным алгоритмом, то есть каждое решение о каждом элементе кластера принимается без повторного сканирования данных или уже существующих кластеров. Используются только метрики, отражающие близость элементов друг к другу.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH использует факт неравномерного распределения данных в пространстве и поэтому не все данные рассматриваются как одинаково важные для построения кластера. Области с большой плотностью обрабатываются как единый кластер. Данные в более разреженных областях могут удаляться (опционально).&lt;br /&gt;
&lt;br /&gt;
3. BIRCH использует всю доступную память для получения наилучших из возможных подкластеров, в то же время минимизируя затраты на операции ввода/вывода. Оптимизация процесса кластеризации достигается за счет использования взвешенно-сбалансированного дерева. При этом время исполнения линейно.&lt;br /&gt;
&lt;br /&gt;
4. BIRCH не требует всего набора данных заранее (при этом просматривает его всего один раз).&lt;br /&gt;
&lt;br /&gt;
=== Недостатки алгоритма ===&lt;br /&gt;
&lt;br /&gt;
1. Алгоритм позволяет работать только с числовыми данными.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH хорошо выделяет только кластеры сферической формы.&lt;br /&gt;
&lt;br /&gt;
3. Существует необходимость в задании пороговых значений.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* [https://code.google.com/archive/p/jbirch/ Java]&lt;br /&gt;
* [http://scikit-learn.org/stable/modules/generated/sklearn.cluster.Birch.html Python]&lt;br /&gt;
* [http://cucis.ece.northwestern.edu/projects/DMS/MineBench.html#description]&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&lt;br /&gt;
[1] Википедия&lt;/div&gt;</summary>
		<author><name>Светлана Морозова</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13530</id>
		<title>Участник:Smirnov.maxim/BIRCH</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13530"/>
		<updated>2016-10-23T16:32:20Z</updated>

		<summary type="html">&lt;p&gt;Светлана Морозова: /* Существующие реализации алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Нахождение полезных для анализа закономерностей в больших объёмах данных с недавних пор вызывает значительный интерес. В связи с этим ввелось и стало активно развиваться такое понятие как &#039;&#039;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7 кластеризация]&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Ранние работы и алгоритмы, разработанные в этой области, не уделяли достаточного внимания анализу очень больших наборов данных или минимизации издержек на процессы ввода-вывода.&lt;br /&gt;
Решением этих проблем стал алгоритм, известный как BIRCH.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIRCH&#039;&#039;&#039; (balanced iterative reducing and clustering using hierarchies)- алгоритм, применяемый в области [https://ru.wikipedia.org/wiki/Data_mining Data mining] и использующий принципы [https://ru.wikipedia.org/wiki/%D0%98%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F иерархической кластеризации].&lt;br /&gt;
&lt;br /&gt;
Если имеется очень большой набор данных, то в пространстве он распределен, как правило, неравномерно. Кластерный анализ определяет места наибольшего и наименьшего скоплений, чтобы таким образом понять всю картину целиком. Кроме того, полученные кластеры визуализируются гораздо нагляднее, чем начальные &amp;quot;сырые&amp;quot; данные.&lt;br /&gt;
Задачей алгоритмов кластеризации является не только простое разбиение данных на кластеры, но и работа в рамках ограниченного объёма доступной памяти (как правило, её объём гораздо меньше, чем размер исходного набора данных) и минимизация времени, требуемого на операции ввода-вывода.&lt;br /&gt;
&lt;br /&gt;
Для наилучшего решения этих проблем BIRCH распределяет входящие данные по кластерам динамически. Для эффективной кластеризации алгоритму требуется всего одно сканирование данных (т.е. с увеличением количества данных сложность увеличивается линейно). А при помощи одной (или более) дополнительных итераций можно и далее улучшать эффективность. BIRCH также является первым алгоритмом, предложенным для эффективного управления &amp;quot;шумами&amp;quot; (данными, которые не вписываются в общее представление модели).&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Теоретическая основа ===&lt;br /&gt;
&lt;br /&gt;
Пусть в кластере имеются &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}, i=1,2,...,N&amp;lt;/math&amp;gt;.&lt;br /&gt;
Тогда &#039;&#039;&#039;центроид&#039;&#039;&#039; &amp;lt;math&amp;gt;{\vec{{X_0}}}&amp;lt;/math&amp;gt;, &#039;&#039;&#039;радиус&#039;&#039;&#039; &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &#039;&#039;&#039;диаметр&#039;&#039;&#039; &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластера определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;{\vec{X_0}}=\frac{\sum_{i=1}^N\vec{X_i}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{\sum_{i=1}^N{(\vec{X_i} - \vec{X_0})}^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{\sum_{i=1}^N\sum_{j=1}^N{(\vec{X_i} - \vec{X_j})}^2}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; - это среднее расстояние от каждой точки до центроида. &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; - это среднее расстояние между парами в кластере. Данные величины являются альтернативными метриками плотности кластера относительно центроида.&lt;br /&gt;
&lt;br /&gt;
Для измерения близости друг к другу двух кластеров вводятся следующие метрики:&lt;br /&gt;
&lt;br /&gt;
пусть даны центроиды двух кластеров &amp;lt;math&amp;gt;\vec{X_{01}}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\vec{X_{02}}&amp;lt;/math&amp;gt;.&lt;br /&gt;
Евклидова метрика &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt; и метрика Манхэттена &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt; между двумя кластерами определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_0 = ((\vec{X_{01}}-\vec{X_{02}})^2)^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_1 = |\vec{X_{01}}-\vec{X_{02}}| = \sum_{i=1}^d |{\vec{X_{01}}}^{(i)}-{\vec{X_{02}}}^{(i)}| &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть имеются два кластера, содержащих соответственно  &amp;lt;math&amp;gt;N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;N_2&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i= 1,2, ...,N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\{\vec{X_j}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j= N_1+1,N_1+2, ...,N_1+N_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Среднее расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &#039;&#039;&#039;среднее внутрикластерное расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &#039;&#039;&#039;дисперсия&#039;&#039;&#039; &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; для двух кластеров определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{\sum_{i=1}^{N_1}\sum_{j=N_1+1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{N_1N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{\sum_{i=1}^{N_1+N_2}\sum_{j=1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_4 = \sum_{k=1}^{N_1+N_2}(\vec{X_k} - \frac{\sum_{i=1}^{N_1+N_2}\vec{X_i}}{N_1+N_2})^2 - \sum_{i=1}^{N_1}(\vec{X_i} - \frac{\sum_{i=1}^{N_1}\vec{X_i}}{N_1})^2 - \sum_{j=N_1+1}^{N_1+N_2}(\vec{X_j} - \frac{\sum_{i=N_1+1}^{N_1+N_2}\vec{X_i}}{N_2})^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Таким образом, величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; относятся к отдельным кластерам, а &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; - к объединению двух кластеров.&lt;br /&gt;
&lt;br /&gt;
=== Кластерный элемент и кластерное дерево ===&lt;br /&gt;
&lt;br /&gt;
В основе концепции алгоритма BIRCH лежат понятия &#039;&#039;&#039;кластерного элемента&#039;&#039;&#039; и &#039;&#039;&#039;кластерного дерева (CF Tree)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====Кластерный элемент ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; Пусть в кластере содержатся  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности  &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;:&amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;i=1,2,...,N&amp;lt;/math&amp;gt;. &lt;br /&gt;
&#039;&#039;&#039;Кластерный элемент (CF)&#039;&#039;&#039; - тройка чисел, характеризующая информацию о кластере: &lt;br /&gt;
&amp;lt;math&amp;gt;CF = (N, \vec{LS}, SS)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - количество элементов входных данных, содержащихся в кластере, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; - линейная сумма входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}\vec{X_i}&amp;lt;/math&amp;gt;), &amp;lt;math&amp;gt;SS&amp;lt;/math&amp;gt; - сумма квадратов входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}{\vec{X_i}}^2&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Теорема&#039;&#039;&#039; Пусть &amp;lt;math&amp;gt;CF_1 = (N_1, \vec{LS_1}, SS_1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;CF_2 = (N_1, \vec{LS_2}, SS_2)&amp;lt;/math&amp;gt; - CF векторы двух непересекающихся кластеров. Тогда при их объединении образуется кластер со следующим CF вектором: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF = CF_1 + CF_2 = (N_1+N_2, \vec{LS_1}+\vec{LS_2}, SS_1+SS_2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Из указанных выше определения и теоремы вытекает тот факт, что при объединении кластеров их CF вектор может вычисляться инкрементно и точно. &lt;br /&gt;
Легко показать, что вычислить величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;, как и обычные метрики, также не составит труда.&lt;br /&gt;
&lt;br /&gt;
Таким образом, в данном случае информацией о кластере является не весь набор точек, а вектор CF. Хранение одного только вектора может показаться неэффективным, но этого вполне достаточно для оперирования всеми необходимыми метриками, на основе которых принимаются решения в алгоритме BIRCH.&lt;br /&gt;
&lt;br /&gt;
==== Кластерное дерево ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; &#039;&#039;&#039;Кластерное дерево (CF Tree)&#039;&#039;&#039; - это взвешенно сбалансированное дерево с двумя параметрами: &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - коэффициент разветвления, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - пороговая величина. Каждый нелистьевой узел дерева имеет не более чем &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; вхождений узлов следующей формы: &amp;lt;math&amp;gt;[CF_i,child_i]&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i=1,2,...,B&amp;lt;/math&amp;gt;, &#039;&#039;child&#039;&#039; - указатель на i-й дочерний узел, &amp;lt;math&amp;gt;CF_i&amp;lt;/math&amp;gt; - CF вектор соответствующего подкластера.&lt;br /&gt;
&lt;br /&gt;
Каждый листьевой узел имеет ссылку на два соседних узла (&#039;&#039;prev&#039;&#039; и &#039;&#039;next&#039;&#039;) для того, чтобы связать все узлы для эффективного сканирования.&lt;br /&gt;
Все листьевые узлы должны удовлетворять пороговому ограничению &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, т.е. диаметр (радиус) не должен превосходить &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;.&lt;br /&gt;
В процессе вставки новых данных CF дерево строится динамически. Оно использует вставку данных для кластеризации точно также как &amp;lt;math&amp;gt;B+&amp;lt;/math&amp;gt; [https://ru.wikipedia.org/wiki/B%2B-%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE дерево] использует её для поиска.&lt;br /&gt;
CF дерево очень компактно, поскольку каждый листьевой узел - это не просто точка, а подкластер (который объединяет множество точек с учётом ограничения &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Операция вставки в &#039;&#039;&#039;CF&#039;&#039;&#039; дерево ====&lt;br /&gt;
&lt;br /&gt;
Опишем алгоритм вставки элемнта &amp;lt;math&amp;gt;Ent&amp;lt;/math&amp;gt; в CF дерево:&lt;br /&gt;
&lt;br /&gt;
1) &#039;&#039;Определение подходящего листа&#039;&#039;: Начиная с корня, алгоритм рекурсивно спускается по CF дереву, выбирая &#039;&#039;&#039;ближайший&#039;&#039;&#039; дочерний узел в соответствии с выбранной метрикой &amp;lt;math&amp;gt;D0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D4&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &#039;&#039;Преобразование листа&#039;&#039;: Когда алгоритм доходит до листа, он находит ближайшую листьевой элемент, скажем, &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;, а затем проверяет, можно ли добавить &#039;&#039;Ent&#039;&#039; к &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt; без нарушения порогового условия. Если да, то с учётом этого изменяется CF вектор для &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;; если нет, то &#039;&#039;Ent&#039;&#039; становится новым элементом листа. Если в листе для этого достаточно места, то шаг окончен, иначе он должен &amp;quot;расщепиться&amp;quot;. Расщепление узла производится при помощи выбора за основу наиболее удалённой друг от друга пары элементов и перераспределение оставшихся элементов в соответствии с выбранным критерием близости.&lt;br /&gt;
&lt;br /&gt;
3) &#039;&#039;Преобразование пути к листу&#039;&#039;: После вставки &#039;&#039;Ent&#039;&#039; в лист мы должны обновить информацию о CF для каждого нелистьевого элемента на пути к листу. При отсутствии расщепления это означает простое сложение CF векторов для отражения факта добавления &#039;&#039;Ent&#039;&#039;. Расщепление листа же требует вставки нового нелистьевого элемента в родительский узел для задания только что созданного листа. Если у родителя есть место для этого элемента, то необходимо просто преобразовать CF векторы на всех более высоких уровнях. В общем случае, однако, нам также придётся расщепить родительский узел, и так далее до корня. Если расщеплён корень, то высота дерева увеличивается на единицу.&lt;br /&gt;
&lt;br /&gt;
4) &#039;&#039;Улучшение слияния&#039;&#039;: Расщепление вызвано ограничением на размер узла, который не зависит от кластеризационных свойств данных. Если во входящем потоке присутствуют &amp;quot;искажённые&amp;quot; (из областей с низкой плотностью) данные, это может повлиять на качество кластеризации, а также уменьшить эффективность использования памяти. Дополнительный шаг алгоритма помогает решить эти проблемы: предположим, что произошло расщепление листа, и распространение этого процесса остановилось на некотором нелистьевом узле &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt;, то есть &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; может вместить дополнительный элемент, полученный после расщепления. Теперь мы сканируем узел &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; для нахождения двух наиболее близких элементов. Если это не пара, отвечающая расщеплению, мы пытаемся объединить их и поставить в соответствие два дочерних узла. Если количество элементов в дочерних узлах  больше B, мы снова расщепляем результат объединения.&lt;br /&gt;
В процессе повторного расщепления, в случае, если один источник собирает достаточно элементов для того, чтобы полностью заполнить узел, оставшиеся элементы передаются другом источнику. В итоге, если объединённые элементы помещаются в одном узле, в нём освобождается место для ещё одного элемента. Тем самым увеличивается степень использования свободного пространства и откладывается дальнейшее расщепление. В ином случае мы улучшаем распределение элементов в двух ближайших подкластерах.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро алгоритма заключается в многократном выполнении операции вставки нового элемента в дерево, в процессе чего требуется вычисление следующих величин:&lt;br /&gt;
&lt;br /&gt;
* радиуса &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; или диаметра &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластерного элемента. Выполняется при попытке вставить новый элемент в один из подкластеров листьевого узла дерева.&lt;br /&gt;
&lt;br /&gt;
* расстояния между двумя элементами. Выполняется при поиске ближайшего по отношению к новому элементу подкластера в узле дерева по одной из рассмотренных в разд. 1.2.1 метрик &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Зная характеристики кластерных элементов &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;, в результате алгебраических преобразований можно получить следующие упрощенные формулы вычисления необходимых значений:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\vec{X_0} = \frac{\vec{LS}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{SS - 2\vec{X_0}\vec{LS} + N(\vec{X_0})^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{2(N*SS - (\vec{LS})^2)}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{N_1*SS_2 + N_2*SS_1 - 2\vec{LS_1}\vec{LS_2}}{N_1*N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{2((N_1+N_2)(SS_1+SS_2)-(\vec{LS_1}+\vec{LS_2})^2)}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Реализация алгоритма BIRCH состояит из следующих четырёх фаз:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 1&#039;&#039;&#039;. Главной задачей фазы 1 является сканирование всех данных и построение в памяти исходного CF дерева, используя заданное количество памяти. Это дерево стремится отразить информацию о кластеризации данных настолько хорошо, насколько это позволяют ограничения по памяти. При этом плотно распределённые данные группируются в подкластеры, а более разрозненные данные удаляются. После завершения фазы 1 вспомогательные вычисления в дальнейших фазах будут:&lt;br /&gt;
&lt;br /&gt;
1) быстрее, потому что (а) больше не нужны операции ввода-вывода, (b) проблема кластеризации начальных данных упрощается до проблемы кластеризации подкластеров в листьях;&lt;br /&gt;
&lt;br /&gt;
2) точнее, потому что (а) большинство данных с низкой плотностью удалены, (b) оставшиеся данные распределены оптимально (в соответствии с доступным количеством памяти);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 2&#039;&#039;&#039;. Данная фаза является опциональной. Известно, что существующие методы глобальной кластеризации, используемые в рамках фазы 3, имеют различные диапазоны входных значений, при которых их реализация наиболее эффективна. Поэтому потенциально существует пробел между размером фазы 1 и входными значениями фазы 3. И фаза 2 как раз является недостающим связующим звеном: так же как и фаза 1, она сканирует листьевые элементы начального CF дерева для того, чтобы построить меньшее дерево, удаляя ещё больше элементов с низкой плотностью и группируя переполненные подкластеры в большие кластеры.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 3&#039;&#039;&#039;. В данной фазе для листьевых элементов применяется (любой подходящий) алгоритм глобальной кластеризации. Существующие алгоритмы кластеризации наборов точек могут также работать с наборами подкластеров, каждый из которых представлен своим CF вектором. Зная CF вектор, можно вычислить центроид и в дальнейшем заменить всю информацию о кластере этим значением (этого достаточно для вычисления большинства необходимых метрик). После фазы 3 мы получаем набор кластеров, который отражает основные характеристики распределяемых данных.&lt;br /&gt;
Однако, всё ещё могут оставаться некоторые неточности, для устранения которых существует фаза 4.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 4&#039;&#039;&#039;. Данная фаза является опциональной и влечёт за собой затраты на дополнительное сканирование данных для корректировки неточностей и дальнейшего улучшения кластеризации. Фаза 4 использует центроиды кластеров, полученные в фазе 3 для как основы и перераспределяет точки входных данных в ближайшие для них основы для получения нового списка кластеров. Фаза 4, если это необходимо пользователю, может быть расширена дополнительными проходами для уверенности в том, что результат приближается к оптимальному.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Для начала проанализируем вычислительную сложность фазы 1.&lt;br /&gt;
Максимальный размер дерева &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt;. Для того чтобы вставить элемент, мы должны пройти путь от корня до листа (это около &amp;lt;math&amp;gt;1+log_B\frac{M}{P}&amp;lt;/math&amp;gt; узлов). В каждом узле в поисках &amp;quot;ближайшего&amp;quot; нам необходимо просмотреть B элементов; сложность для каждого элемента пропорциональна размерности &#039;&#039;d&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Поэтому сложность вставки всех входных точек &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В случае, когда необходимо перестроить дерево, предположим, что ES - это размер CF элемента. Существует максимум &amp;lt;math&amp;gt;\frac{M}{ES}&amp;lt;/math&amp;gt; листьевых элементов для вставки, поэтому сложность повторной вставки листьевых элементов &amp;lt;math&amp;gt;O(d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Количество итераций перестройки дерева зависит от пороговой величины. На самом деле, это около &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; (двоичное основание появилось из-за того, что мы не можем провести оценку более чем в 2 раза отличающуюся от текущего размера). &amp;lt;math&amp;gt;N_0&amp;lt;/math&amp;gt; - это число входных точек, загруженных в память с пороговым ограничением &amp;lt;math&amp;gt;T_0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Соответственно, итоговая сложность фазы 1 &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P})+log_2\frac{N}{N_0}*d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Анализ фазы 2 проводится аналогично.&lt;br /&gt;
&lt;br /&gt;
Что касается операций ввода-вывода, то в фазе 1 данные сканируются один раз, а в фазе 2 не сканируются вовсе.&lt;br /&gt;
Некоторое количество вычислений связано с удалением точек из областей с низкой плотностью.&lt;br /&gt;
Если количество доступной для этой операции памяти не больше &#039;&#039;M&#039;&#039; и проведено порядка &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; перестроек дерева, то сложность ввода-вывода для фазы 1 существенно не отличается от сложности чтения из файла. Основываясь рассуждениях выше, сложность фаз 1 и 2 будет линейно увеличиваться с ростом N.&lt;br /&gt;
&lt;br /&gt;
В фазе 3 нет операций ввода-вывода. Её сложность ограничена константой, которая зависит от максимального размера входных данных, и варианта выбранного алгоритма для кластеризации. &lt;br /&gt;
&lt;br /&gt;
Фаза 4 снова сканирует данные и записывает каждую точку в подходящий кластер; время работы пропорционально &amp;lt;math&amp;gt;N*K&amp;lt;/math&amp;gt;.   &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Достоинства алгоритма ===&lt;br /&gt;
По сравнению с предыдущими методами BIRCH обладает следующими достоинствами:&lt;br /&gt;
&lt;br /&gt;
1. BIRCH является локальным алгоритмом, то есть каждое решение о каждом элементе кластера принимается без повторного сканирования данных или уже существующих кластеров. Используются только метрики, отражающие близость элементов друг к другу.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH использует факт неравномерного распределения данных в пространстве и поэтому не все данные рассматриваются как одинаково важные для построения кластера. Области с большой плотностью обрабатываются как единый кластер. Данные в более разреженных областях могут удаляться (опционально).&lt;br /&gt;
&lt;br /&gt;
3. BIRCH использует всю доступную память для получения наилучших из возможных подкластеров, в то же время минимизируя затраты на операции ввода/вывода. Оптимизация процесса кластеризации достигается за счет использования взвешенно-сбалансированного дерева. При этом время исполнения линейно.&lt;br /&gt;
&lt;br /&gt;
4. BIRCH не требует всего набора данных заранее (при этом просматривает его всего один раз).&lt;br /&gt;
&lt;br /&gt;
=== Недостатки алгоритма ===&lt;br /&gt;
&lt;br /&gt;
1. Алгоритм позволяет работать только с числовыми данными.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH хорошо выделяет только кластеры сферической формы.&lt;br /&gt;
&lt;br /&gt;
3. Существует необходимость в задании пороговых значений.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* [https://code.google.com/archive/p/jbirch/ Java]&lt;br /&gt;
* [http://scikit-learn.org/stable/modules/generated/sklearn.cluster.Birch.html Python]&lt;br /&gt;
* [http://cucis.ece.northwestern.edu/projects/DMS/MineBench.html#description]&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&lt;br /&gt;
[1] Википедия&lt;/div&gt;</summary>
		<author><name>Светлана Морозова</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13526</id>
		<title>Участник:Smirnov.maxim/BIRCH</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13526"/>
		<updated>2016-10-23T16:20:59Z</updated>

		<summary type="html">&lt;p&gt;Светлана Морозова: /* Существующие реализации алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Нахождение полезных для анализа закономерностей в больших объёмах данных с недавних пор вызывает значительный интерес. В связи с этим ввелось и стало активно развиваться такое понятие как &#039;&#039;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7 кластеризация]&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Ранние работы и алгоритмы, разработанные в этой области, не уделяли достаточного внимания анализу очень больших наборов данных или минимизации издержек на процессы ввода-вывода.&lt;br /&gt;
Решением этих проблем стал алгоритм, известный как BIRCH.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIRCH&#039;&#039;&#039; (balanced iterative reducing and clustering using hierarchies)- алгоритм, применяемый в области [https://ru.wikipedia.org/wiki/Data_mining Data mining] и использующий принципы [https://ru.wikipedia.org/wiki/%D0%98%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F иерархической кластеризации].&lt;br /&gt;
&lt;br /&gt;
Если имеется очень большой набор данных, то в пространстве он распределен, как правило, неравномерно. Кластерный анализ определяет места наибольшего и наименьшего скоплений, чтобы таким образом понять всю картину целиком. Кроме того, полученные кластеры визуализируются гораздо нагляднее, чем начальные &amp;quot;сырые&amp;quot; данные.&lt;br /&gt;
Задачей алгоритмов кластеризации является не только простое разбиение данных на кластеры, но и работа в рамках ограниченного объёма доступной памяти (как правило, её объём гораздо меньше, чем размер исходного набора данных) и минимизация времени, требуемого на операции ввода-вывода.&lt;br /&gt;
&lt;br /&gt;
Для наилучшего решения этих проблем BIRCH распределяет входящие данные по кластерам динамически. Для эффективной кластеризации алгоритму требуется всего одно сканирование данных (т.е. с увеличением количества данных сложность увеличивается линейно). А при помощи одной (или более) дополнительных итераций можно и далее улучшать эффективность. BIRCH также является первым алгоритмом, предложенным для эффективного управления &amp;quot;шумами&amp;quot; (данными, которые не вписываются в общее представление модели).&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Теоретическая основа ===&lt;br /&gt;
&lt;br /&gt;
Пусть в кластере имеются &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}, i=1,2,...,N&amp;lt;/math&amp;gt;.&lt;br /&gt;
Тогда &#039;&#039;&#039;центроид&#039;&#039;&#039; &amp;lt;math&amp;gt;{\vec{{X_0}}}&amp;lt;/math&amp;gt;, &#039;&#039;&#039;радиус&#039;&#039;&#039; &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &#039;&#039;&#039;диаметр&#039;&#039;&#039; &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластера определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;{\vec{X_0}}=\frac{\sum_{i=1}^N\vec{X_i}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{\sum_{i=1}^N{(\vec{X_i} - \vec{X_0})}^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{\sum_{i=1}^N\sum_{j=1}^N{(\vec{X_i} - \vec{X_j})}^2}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; - это среднее расстояние от каждой точки до центроида. &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; - это среднее расстояние между парами в кластере. Данные величины являются альтернативными метриками плотности кластера относительно центроида.&lt;br /&gt;
&lt;br /&gt;
Для измерения близости друг к другу двух кластеров вводятся следующие метрики:&lt;br /&gt;
&lt;br /&gt;
пусть даны центроиды двух кластеров &amp;lt;math&amp;gt;\vec{X_{01}}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\vec{X_{02}}&amp;lt;/math&amp;gt;.&lt;br /&gt;
Евклидова метрика &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt; и метрика Манхэттена &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt; между двумя кластерами определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_0 = ((\vec{X_{01}}-\vec{X_{02}})^2)^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_1 = |\vec{X_{01}}-\vec{X_{02}}| = \sum_{i=1}^d |{\vec{X_{01}}}^{(i)}-{\vec{X_{02}}}^{(i)}| &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть имеются два кластера, содержащих соответственно  &amp;lt;math&amp;gt;N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;N_2&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i= 1,2, ...,N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\{\vec{X_j}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j= N_1+1,N_1+2, ...,N_1+N_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Среднее расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &#039;&#039;&#039;среднее внутрикластерное расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &#039;&#039;&#039;дисперсия&#039;&#039;&#039; &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; для двух кластеров определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{\sum_{i=1}^{N_1}\sum_{j=N_1+1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{N_1N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{\sum_{i=1}^{N_1+N_2}\sum_{j=1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_4 = \sum_{k=1}^{N_1+N_2}(\vec{X_k} - \frac{\sum_{i=1}^{N_1+N_2}\vec{X_i}}{N_1+N_2})^2 - \sum_{i=1}^{N_1}(\vec{X_i} - \frac{\sum_{i=1}^{N_1}\vec{X_i}}{N_1})^2 - \sum_{j=N_1+1}^{N_1+N_2}(\vec{X_j} - \frac{\sum_{i=N_1+1}^{N_1+N_2}\vec{X_i}}{N_2})^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Таким образом, величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; относятся к отдельным кластерам, а &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; - к объединению двух кластеров.&lt;br /&gt;
&lt;br /&gt;
=== Кластерный элемент и кластерное дерево ===&lt;br /&gt;
&lt;br /&gt;
В основе концепции алгоритма BIRCH лежат понятия &#039;&#039;&#039;кластерного элемента&#039;&#039;&#039; и &#039;&#039;&#039;кластерного дерева (CF Tree)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====Кластерный элемент ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; Пусть в кластере содержатся  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности  &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;:&amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;i=1,2,...,N&amp;lt;/math&amp;gt;. &lt;br /&gt;
&#039;&#039;&#039;Кластерный элемент (CF)&#039;&#039;&#039; - тройка чисел, характеризующая информацию о кластере: &lt;br /&gt;
&amp;lt;math&amp;gt;CF = (N, \vec{LS}, SS)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - количество элементов входных данных, содержащихся в кластере, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; - линейная сумма входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}\vec{X_i}&amp;lt;/math&amp;gt;), &amp;lt;math&amp;gt;SS&amp;lt;/math&amp;gt; - сумма квадратов входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}{\vec{X_i}}^2&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Теорема&#039;&#039;&#039; Пусть &amp;lt;math&amp;gt;CF_1 = (N_1, \vec{LS_1}, SS_1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;CF_2 = (N_1, \vec{LS_2}, SS_2)&amp;lt;/math&amp;gt; - CF векторы двух непересекающихся кластеров. Тогда при их объединении образуется кластер со следующим CF вектором: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF = CF_1 + CF_2 = (N_1+N_2, \vec{LS_1}+\vec{LS_2}, SS_1+SS_2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Из указанных выше определения и теоремы вытекает тот факт, что при объединении кластеров их CF вектор может вычисляться инкрементно и точно. &lt;br /&gt;
Легко показать, что вычислить величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;, как и обычные метрики, также не составит труда.&lt;br /&gt;
&lt;br /&gt;
Таким образом, в данном случае информацией о кластере является не весь набор точек, а вектор CF. Хранение одного только вектора может показаться неэффективным, но этого вполне достаточно для оперирования всеми необходимыми метриками, на основе которых принимаются решения в алгоритме BIRCH.&lt;br /&gt;
&lt;br /&gt;
==== Кластерное дерево ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; &#039;&#039;&#039;Кластерное дерево (CF Tree)&#039;&#039;&#039; - это взвешенно сбалансированное дерево с двумя параметрами: &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - коэффициент разветвления, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - пороговая величина. Каждый нелистьевой узел дерева имеет не более чем &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; вхождений узлов следующей формы: &amp;lt;math&amp;gt;[CF_i,child_i]&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i=1,2,...,B&amp;lt;/math&amp;gt;, &#039;&#039;child&#039;&#039; - указатель на i-й дочерний узел, &amp;lt;math&amp;gt;CF_i&amp;lt;/math&amp;gt; - CF вектор соответствующего подкластера.&lt;br /&gt;
&lt;br /&gt;
Каждый листьевой узел имеет ссылку на два соседних узла (&#039;&#039;prev&#039;&#039; и &#039;&#039;next&#039;&#039;) для того, чтобы связать все узлы для эффективного сканирования.&lt;br /&gt;
Все листьевые узлы должны удовлетворять пороговому ограничению &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, т.е. диаметр (радиус) не должен превосходить &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;.&lt;br /&gt;
В процессе вставки новых данных CF дерево строится динамически. Оно использует вставку данных для кластеризации точно также как &amp;lt;math&amp;gt;B+&amp;lt;/math&amp;gt; [https://ru.wikipedia.org/wiki/B%2B-%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE дерево] использует её для поиска.&lt;br /&gt;
CF дерево очень компактно, поскольку каждый листьевой узел - это не просто точка, а подкластер (который объединяет множество точек с учётом ограничения &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Операция вставки в &#039;&#039;&#039;CF&#039;&#039;&#039; дерево ====&lt;br /&gt;
&lt;br /&gt;
Опишем алгоритм вставки элемнта &amp;lt;math&amp;gt;Ent&amp;lt;/math&amp;gt; в CF дерево:&lt;br /&gt;
&lt;br /&gt;
1) &#039;&#039;Определение подходящего листа&#039;&#039;: Начиная с корня, алгоритм рекурсивно спускается по CF дереву, выбирая &#039;&#039;&#039;ближайший&#039;&#039;&#039; дочерний узел в соответствии с выбранной метрикой &amp;lt;math&amp;gt;D0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D4&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &#039;&#039;Преобразование листа&#039;&#039;: Когда алгоритм доходит до листа, он находит ближайшую листьевой элемент, скажем, &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;, а затем проверяет, можно ли добавить &#039;&#039;Ent&#039;&#039; к &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt; без нарушения порогового условия. Если да, то с учётом этого изменяется CF вектор для &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;; если нет, то &#039;&#039;Ent&#039;&#039; становится новым элементом листа. Если в листе для этого достаточно места, то шаг окончен, иначе он должен &amp;quot;расщепиться&amp;quot;. Расщепление узла производится при помощи выбора за основу наиболее удалённой друг от друга пары элементов и перераспределение оставшихся элементов в соответствии с выбранным критерием близости.&lt;br /&gt;
&lt;br /&gt;
3) &#039;&#039;Преобразование пути к листу&#039;&#039;: После вставки &#039;&#039;Ent&#039;&#039; в лист мы должны обновить информацию о CF для каждого нелистьевого элемента на пути к листу. При отсутствии расщепления это означает простое сложение CF векторов для отражения факта добавления &#039;&#039;Ent&#039;&#039;. Расщепление листа же требует вставки нового нелистьевого элемента в родительский узел для задания только что созданного листа. Если у родителя есть место для этого элемента, то необходимо просто преобразовать CF векторы на всех более высоких уровнях. В общем случае, однако, нам также придётся расщепить родительский узел, и так далее до корня. Если расщеплён корень, то высота дерева увеличивается на единицу.&lt;br /&gt;
&lt;br /&gt;
4) &#039;&#039;Улучшение слияния&#039;&#039;: Расщепление вызвано ограничением на размер узла, который не зависит от кластеризационных свойств данных. Если во входящем потоке присутствуют &amp;quot;искажённые&amp;quot; (из областей с низкой плотностью) данные, это может повлиять на качество кластеризации, а также уменьшить эффективность использования памяти. Дополнительный шаг алгоритма помогает решить эти проблемы: предположим, что произошло расщепление листа, и распространение этого процесса остановилось на некотором нелистьевом узле &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt;, то есть &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; может вместить дополнительный элемент, полученный после расщепления. Теперь мы сканируем узел &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; для нахождения двух наиболее близких элементов. Если это не пара, отвечающая расщеплению, мы пытаемся объединить их и поставить в соответствие два дочерних узла. Если количество элементов в дочерних узлах  больше B, мы снова расщепляем результат объединения.&lt;br /&gt;
В процессе повторного расщепления, в случае, если один источник собирает достаточно элементов для того, чтобы полностью заполнить узел, оставшиеся элементы передаются другом источнику. В итоге, если объединённые элементы помещаются в одном узле, в нём освобождается место для ещё одного элемента. Тем самым увеличивается степень использования свободного пространства и откладывается дальнейшее расщепление. В ином случае мы улучшаем распределение элементов в двух ближайших подкластерах.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро алгоритма заключается в многократном выполнении операции вставки нового элемента в дерево, в процессе чего требуется вычисление следующих величин:&lt;br /&gt;
&lt;br /&gt;
* радиуса &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; или диаметра &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластерного элемента. Выполняется при попытке вставить новый элемент в один из подкластеров листьевого узла дерева.&lt;br /&gt;
&lt;br /&gt;
* расстояния между двумя элементами. Выполняется при поиске ближайшего по отношению к новому элементу подкластера в узле дерева по одной из рассмотренных в разд. 1.2.1 метрик &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Зная характеристики кластерных элементов &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;, в результате алгебраических преобразований можно получить следующие упрощенные формулы вычисления необходимых значений:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\vec{X_0} = \frac{\vec{LS}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{SS - 2\vec{X_0}\vec{LS} + N(\vec{X_0})^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{2(N*SS - (\vec{LS})^2)}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{N_1*SS_2 + N_2*SS_1 - 2\vec{LS_1}\vec{LS_2}}{N_1*N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{2((N_1+N_2)(SS_1+SS_2)-(\vec{LS_1}+\vec{LS_2})^2)}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Реализация алгоритма BIRCH состояит из следующих четырёх фаз:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 1&#039;&#039;&#039;. Главной задачей фазы 1 является сканирование всех данных и построение в памяти исходного CF дерева, используя заданное количество памяти. Это дерево стремится отразить информацию о кластеризации данных настолько хорошо, насколько это позволяют ограничения по памяти. При этом плотно распределённые данные группируются в подкластеры, а более разрозненные данные удаляются. После завершения фазы 1 вспомогательные вычисления в дальнейших фазах будут:&lt;br /&gt;
&lt;br /&gt;
1) быстрее, потому что (а) больше не нужны операции ввода-вывода, (b) проблема кластеризации начальных данных упрощается до проблемы кластеризации подкластеров в листьях;&lt;br /&gt;
&lt;br /&gt;
2) точнее, потому что (а) большинство данных с низкой плотностью удалены, (b) оставшиеся данные распределены оптимально (в соответствии с доступным количеством памяти);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 2&#039;&#039;&#039;. Данная фаза является опциональной. Известно, что существующие методы глобальной кластеризации, используемые в рамках фазы 3, имеют различные диапазоны входных значений, при которых их реализация наиболее эффективна. Поэтому потенциально существует пробел между размером фазы 1 и входными значениями фазы 3. И фаза 2 как раз является недостающим связующим звеном: так же как и фаза 1, она сканирует листьевые элементы начального CF дерева для того, чтобы построить меньшее дерево, удаляя ещё больше элементов с низкой плотностью и группируя переполненные подкластеры в большие кластеры.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 3&#039;&#039;&#039;. В данной фазе для листьевых элементов применяется (любой подходящий) алгоритм глобальной кластеризации. Существующие алгоритмы кластеризации наборов точек могут также работать с наборами подкластеров, каждый из которых представлен своим CF вектором. Зная CF вектор, можно вычислить центроид и в дальнейшем заменить всю информацию о кластере этим значением (этого достаточно для вычисления большинства необходимых метрик). После фазы 3 мы получаем набор кластеров, который отражает основные характеристики распределяемых данных.&lt;br /&gt;
Однако, всё ещё могут оставаться некоторые неточности, для устранения которых существует фаза 4.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 4&#039;&#039;&#039;. Данная фаза является опциональной и влечёт за собой затраты на дополнительное сканирование данных для корректировки неточностей и дальнейшего улучшения кластеризации. Фаза 4 использует центроиды кластеров, полученные в фазе 3 для как основы и перераспределяет точки входных данных в ближайшие для них основы для получения нового списка кластеров. Фаза 4, если это необходимо пользователю, может быть расширена дополнительными проходами для уверенности в том, что результат приближается к оптимальному.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Для начала проанализируем вычислительную сложность фазы 1.&lt;br /&gt;
Максимальный размер дерева &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt;. Для того чтобы вставить элемент, мы должны пройти путь от корня до листа (это около &amp;lt;math&amp;gt;1+log_B\frac{M}{P}&amp;lt;/math&amp;gt; узлов). В каждом узле в поисках &amp;quot;ближайшего&amp;quot; нам необходимо просмотреть B элементов; сложность для каждого элемента пропорциональна размерности &#039;&#039;d&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Поэтому сложность вставки всех входных точек &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В случае, когда необходимо перестроить дерево, предположим, что ES - это размер CF элемента. Существует максимум &amp;lt;math&amp;gt;\frac{M}{ES}&amp;lt;/math&amp;gt; листьевых элементов для вставки, поэтому сложность повторной вставки листьевых элементов &amp;lt;math&amp;gt;O(d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Количество итераций перестройки дерева зависит от пороговой величины. На самом деле, это около &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; (двоичное основание появилось из-за того, что мы не можем провести оценку более чем в 2 раза отличающуюся от текущего размера). &amp;lt;math&amp;gt;N_0&amp;lt;/math&amp;gt; - это число входных точек, загруженных в память с пороговым ограничением &amp;lt;math&amp;gt;T_0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Соответственно, итоговая сложность фазы 1 &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P})+log_2\frac{N}{N_0}*d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Анализ фазы 2 проводится аналогично.&lt;br /&gt;
&lt;br /&gt;
Что касается операций ввода-вывода, то в фазе 1 данные сканируются один раз, а в фазе 2 не сканируются вовсе.&lt;br /&gt;
Некоторое количество вычислений связано с удалением точек из областей с низкой плотностью.&lt;br /&gt;
Если количество доступной для этой операции памяти не больше &#039;&#039;M&#039;&#039; и проведено порядка &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; перестроек дерева, то сложность ввода-вывода для фазы 1 существенно не отличается от сложности чтения из файла. Основываясь рассуждениях выше, сложность фаз 1 и 2 будет линейно увеличиваться с ростом N.&lt;br /&gt;
&lt;br /&gt;
В фазе 3 нет операций ввода-вывода. Её сложность ограничена константой, которая зависит от максимального размера входных данных, и варианта выбранного алгоритма для кластеризации. &lt;br /&gt;
&lt;br /&gt;
Фаза 4 снова сканирует данные и записывает каждую точку в подходящий кластер; время работы пропорционально &amp;lt;math&amp;gt;N*K&amp;lt;/math&amp;gt;.   &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Достоинства алгоритма ===&lt;br /&gt;
По сравнению с предыдущими методами BIRCH обладает следующими достоинствами:&lt;br /&gt;
&lt;br /&gt;
1. BIRCH является локальным алгоритмом, то есть каждое решение о каждом элементе кластера принимается без повторного сканирования данных или уже существующих кластеров. Используются только метрики, отражающие близость элементов друг к другу.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH использует факт неравномерного распределения данных в пространстве и поэтому не все данные рассматриваются как одинаково важные для построения кластера. Области с большой плотностью обрабатываются как единый кластер. Данные в более разреженных областях могут удаляться (опционально).&lt;br /&gt;
&lt;br /&gt;
3. BIRCH использует всю доступную память для получения наилучших из возможных подкластеров, в то же время минимизируя затраты на операции ввода/вывода. Оптимизация процесса кластеризации достигается за счет использования взвешенно-сбалансированного дерева. При этом время исполнения линейно.&lt;br /&gt;
&lt;br /&gt;
4. BIRCH не требует всего набора данных заранее (при этом просматривает его всего один раз).&lt;br /&gt;
&lt;br /&gt;
=== Недостатки алгоритма ===&lt;br /&gt;
&lt;br /&gt;
1. Алгоритм позволяет работать только с числовыми данными.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH хорошо выделяет только кластеры сферической формы.&lt;br /&gt;
&lt;br /&gt;
3. Существует необходимость в задании пороговых значений.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Выводы для классов архитектур ==&lt;br /&gt;
&lt;br /&gt;
== Существующие реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
* [https://code.google.com/archive/p/jbirch/ Java]&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&lt;br /&gt;
[1] Википедия&lt;/div&gt;</summary>
		<author><name>Светлана Морозова</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13525</id>
		<title>Участник:Smirnov.maxim/BIRCH</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13525"/>
		<updated>2016-10-23T16:15:47Z</updated>

		<summary type="html">&lt;p&gt;Светлана Морозова: /* Особенности реализации последовательного алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Нахождение полезных для анализа закономерностей в больших объёмах данных с недавних пор вызывает значительный интерес. В связи с этим ввелось и стало активно развиваться такое понятие как &#039;&#039;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7 кластеризация]&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Ранние работы и алгоритмы, разработанные в этой области, не уделяли достаточного внимания анализу очень больших наборов данных или минимизации издержек на процессы ввода-вывода.&lt;br /&gt;
Решением этих проблем стал алгоритм, известный как BIRCH.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIRCH&#039;&#039;&#039; (balanced iterative reducing and clustering using hierarchies)- алгоритм, применяемый в области [https://ru.wikipedia.org/wiki/Data_mining Data mining] и использующий принципы [https://ru.wikipedia.org/wiki/%D0%98%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F иерархической кластеризации].&lt;br /&gt;
&lt;br /&gt;
Если имеется очень большой набор данных, то в пространстве он распределен, как правило, неравномерно. Кластерный анализ определяет места наибольшего и наименьшего скоплений, чтобы таким образом понять всю картину целиком. Кроме того, полученные кластеры визуализируются гораздо нагляднее, чем начальные &amp;quot;сырые&amp;quot; данные.&lt;br /&gt;
Задачей алгоритмов кластеризации является не только простое разбиение данных на кластеры, но и работа в рамках ограниченного объёма доступной памяти (как правило, её объём гораздо меньше, чем размер исходного набора данных) и минимизация времени, требуемого на операции ввода-вывода.&lt;br /&gt;
&lt;br /&gt;
Для наилучшего решения этих проблем BIRCH распределяет входящие данные по кластерам динамически. Для эффективной кластеризации алгоритму требуется всего одно сканирование данных (т.е. с увеличением количества данных сложность увеличивается линейно). А при помощи одной (или более) дополнительных итераций можно и далее улучшать эффективность. BIRCH также является первым алгоритмом, предложенным для эффективного управления &amp;quot;шумами&amp;quot; (данными, которые не вписываются в общее представление модели).&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Теоретическая основа ===&lt;br /&gt;
&lt;br /&gt;
Пусть в кластере имеются &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}, i=1,2,...,N&amp;lt;/math&amp;gt;.&lt;br /&gt;
Тогда &#039;&#039;&#039;центроид&#039;&#039;&#039; &amp;lt;math&amp;gt;{\vec{{X_0}}}&amp;lt;/math&amp;gt;, &#039;&#039;&#039;радиус&#039;&#039;&#039; &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &#039;&#039;&#039;диаметр&#039;&#039;&#039; &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластера определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;{\vec{X_0}}=\frac{\sum_{i=1}^N\vec{X_i}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{\sum_{i=1}^N{(\vec{X_i} - \vec{X_0})}^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{\sum_{i=1}^N\sum_{j=1}^N{(\vec{X_i} - \vec{X_j})}^2}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; - это среднее расстояние от каждой точки до центроида. &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; - это среднее расстояние между парами в кластере. Данные величины являются альтернативными метриками плотности кластера относительно центроида.&lt;br /&gt;
&lt;br /&gt;
Для измерения близости друг к другу двух кластеров вводятся следующие метрики:&lt;br /&gt;
&lt;br /&gt;
пусть даны центроиды двух кластеров &amp;lt;math&amp;gt;\vec{X_{01}}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\vec{X_{02}}&amp;lt;/math&amp;gt;.&lt;br /&gt;
Евклидова метрика &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt; и метрика Манхэттена &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt; между двумя кластерами определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_0 = ((\vec{X_{01}}-\vec{X_{02}})^2)^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_1 = |\vec{X_{01}}-\vec{X_{02}}| = \sum_{i=1}^d |{\vec{X_{01}}}^{(i)}-{\vec{X_{02}}}^{(i)}| &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть имеются два кластера, содержащих соответственно  &amp;lt;math&amp;gt;N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;N_2&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i= 1,2, ...,N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\{\vec{X_j}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j= N_1+1,N_1+2, ...,N_1+N_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Среднее расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &#039;&#039;&#039;среднее внутрикластерное расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &#039;&#039;&#039;дисперсия&#039;&#039;&#039; &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; для двух кластеров определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{\sum_{i=1}^{N_1}\sum_{j=N_1+1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{N_1N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{\sum_{i=1}^{N_1+N_2}\sum_{j=1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_4 = \sum_{k=1}^{N_1+N_2}(\vec{X_k} - \frac{\sum_{i=1}^{N_1+N_2}\vec{X_i}}{N_1+N_2})^2 - \sum_{i=1}^{N_1}(\vec{X_i} - \frac{\sum_{i=1}^{N_1}\vec{X_i}}{N_1})^2 - \sum_{j=N_1+1}^{N_1+N_2}(\vec{X_j} - \frac{\sum_{i=N_1+1}^{N_1+N_2}\vec{X_i}}{N_2})^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Таким образом, величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; относятся к отдельным кластерам, а &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; - к объединению двух кластеров.&lt;br /&gt;
&lt;br /&gt;
=== Кластерный элемент и кластерное дерево ===&lt;br /&gt;
&lt;br /&gt;
В основе концепции алгоритма BIRCH лежат понятия &#039;&#039;&#039;кластерного элемента&#039;&#039;&#039; и &#039;&#039;&#039;кластерного дерева (CF Tree)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====Кластерный элемент ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; Пусть в кластере содержатся  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности  &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;:&amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;i=1,2,...,N&amp;lt;/math&amp;gt;. &lt;br /&gt;
&#039;&#039;&#039;Кластерный элемент (CF)&#039;&#039;&#039; - тройка чисел, характеризующая информацию о кластере: &lt;br /&gt;
&amp;lt;math&amp;gt;CF = (N, \vec{LS}, SS)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - количество элементов входных данных, содержащихся в кластере, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; - линейная сумма входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}\vec{X_i}&amp;lt;/math&amp;gt;), &amp;lt;math&amp;gt;SS&amp;lt;/math&amp;gt; - сумма квадратов входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}{\vec{X_i}}^2&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Теорема&#039;&#039;&#039; Пусть &amp;lt;math&amp;gt;CF_1 = (N_1, \vec{LS_1}, SS_1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;CF_2 = (N_1, \vec{LS_2}, SS_2)&amp;lt;/math&amp;gt; - CF векторы двух непересекающихся кластеров. Тогда при их объединении образуется кластер со следующим CF вектором: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF = CF_1 + CF_2 = (N_1+N_2, \vec{LS_1}+\vec{LS_2}, SS_1+SS_2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Из указанных выше определения и теоремы вытекает тот факт, что при объединении кластеров их CF вектор может вычисляться инкрементно и точно. &lt;br /&gt;
Легко показать, что вычислить величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;, как и обычные метрики, также не составит труда.&lt;br /&gt;
&lt;br /&gt;
Таким образом, в данном случае информацией о кластере является не весь набор точек, а вектор CF. Хранение одного только вектора может показаться неэффективным, но этого вполне достаточно для оперирования всеми необходимыми метриками, на основе которых принимаются решения в алгоритме BIRCH.&lt;br /&gt;
&lt;br /&gt;
==== Кластерное дерево ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; &#039;&#039;&#039;Кластерное дерево (CF Tree)&#039;&#039;&#039; - это взвешенно сбалансированное дерево с двумя параметрами: &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - коэффициент разветвления, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - пороговая величина. Каждый нелистьевой узел дерева имеет не более чем &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; вхождений узлов следующей формы: &amp;lt;math&amp;gt;[CF_i,child_i]&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i=1,2,...,B&amp;lt;/math&amp;gt;, &#039;&#039;child&#039;&#039; - указатель на i-й дочерний узел, &amp;lt;math&amp;gt;CF_i&amp;lt;/math&amp;gt; - CF вектор соответствующего подкластера.&lt;br /&gt;
&lt;br /&gt;
Каждый листьевой узел имеет ссылку на два соседних узла (&#039;&#039;prev&#039;&#039; и &#039;&#039;next&#039;&#039;) для того, чтобы связать все узлы для эффективного сканирования.&lt;br /&gt;
Все листьевые узлы должны удовлетворять пороговому ограничению &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, т.е. диаметр (радиус) не должен превосходить &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;.&lt;br /&gt;
В процессе вставки новых данных CF дерево строится динамически. Оно использует вставку данных для кластеризации точно также как &amp;lt;math&amp;gt;B+&amp;lt;/math&amp;gt; [https://ru.wikipedia.org/wiki/B%2B-%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE дерево] использует её для поиска.&lt;br /&gt;
CF дерево очень компактно, поскольку каждый листьевой узел - это не просто точка, а подкластер (который объединяет множество точек с учётом ограничения &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Операция вставки в &#039;&#039;&#039;CF&#039;&#039;&#039; дерево ====&lt;br /&gt;
&lt;br /&gt;
Опишем алгоритм вставки элемнта &amp;lt;math&amp;gt;Ent&amp;lt;/math&amp;gt; в CF дерево:&lt;br /&gt;
&lt;br /&gt;
1) &#039;&#039;Определение подходящего листа&#039;&#039;: Начиная с корня, алгоритм рекурсивно спускается по CF дереву, выбирая &#039;&#039;&#039;ближайший&#039;&#039;&#039; дочерний узел в соответствии с выбранной метрикой &amp;lt;math&amp;gt;D0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D4&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &#039;&#039;Преобразование листа&#039;&#039;: Когда алгоритм доходит до листа, он находит ближайшую листьевой элемент, скажем, &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;, а затем проверяет, можно ли добавить &#039;&#039;Ent&#039;&#039; к &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt; без нарушения порогового условия. Если да, то с учётом этого изменяется CF вектор для &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;; если нет, то &#039;&#039;Ent&#039;&#039; становится новым элементом листа. Если в листе для этого достаточно места, то шаг окончен, иначе он должен &amp;quot;расщепиться&amp;quot;. Расщепление узла производится при помощи выбора за основу наиболее удалённой друг от друга пары элементов и перераспределение оставшихся элементов в соответствии с выбранным критерием близости.&lt;br /&gt;
&lt;br /&gt;
3) &#039;&#039;Преобразование пути к листу&#039;&#039;: После вставки &#039;&#039;Ent&#039;&#039; в лист мы должны обновить информацию о CF для каждого нелистьевого элемента на пути к листу. При отсутствии расщепления это означает простое сложение CF векторов для отражения факта добавления &#039;&#039;Ent&#039;&#039;. Расщепление листа же требует вставки нового нелистьевого элемента в родительский узел для задания только что созданного листа. Если у родителя есть место для этого элемента, то необходимо просто преобразовать CF векторы на всех более высоких уровнях. В общем случае, однако, нам также придётся расщепить родительский узел, и так далее до корня. Если расщеплён корень, то высота дерева увеличивается на единицу.&lt;br /&gt;
&lt;br /&gt;
4) &#039;&#039;Улучшение слияния&#039;&#039;: Расщепление вызвано ограничением на размер узла, который не зависит от кластеризационных свойств данных. Если во входящем потоке присутствуют &amp;quot;искажённые&amp;quot; (из областей с низкой плотностью) данные, это может повлиять на качество кластеризации, а также уменьшить эффективность использования памяти. Дополнительный шаг алгоритма помогает решить эти проблемы: предположим, что произошло расщепление листа, и распространение этого процесса остановилось на некотором нелистьевом узле &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt;, то есть &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; может вместить дополнительный элемент, полученный после расщепления. Теперь мы сканируем узел &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; для нахождения двух наиболее близких элементов. Если это не пара, отвечающая расщеплению, мы пытаемся объединить их и поставить в соответствие два дочерних узла. Если количество элементов в дочерних узлах  больше B, мы снова расщепляем результат объединения.&lt;br /&gt;
В процессе повторного расщепления, в случае, если один источник собирает достаточно элементов для того, чтобы полностью заполнить узел, оставшиеся элементы передаются другом источнику. В итоге, если объединённые элементы помещаются в одном узле, в нём освобождается место для ещё одного элемента. Тем самым увеличивается степень использования свободного пространства и откладывается дальнейшее расщепление. В ином случае мы улучшаем распределение элементов в двух ближайших подкластерах.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро алгоритма заключается в многократном выполнении операции вставки нового элемента в дерево, в процессе чего требуется вычисление следующих величин:&lt;br /&gt;
&lt;br /&gt;
* радиуса &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; или диаметра &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластерного элемента. Выполняется при попытке вставить новый элемент в один из подкластеров листьевого узла дерева.&lt;br /&gt;
&lt;br /&gt;
* расстояния между двумя элементами. Выполняется при поиске ближайшего по отношению к новому элементу подкластера в узле дерева по одной из рассмотренных в разд. 1.2.1 метрик &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Зная характеристики кластерных элементов &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;, в результате алгебраических преобразований можно получить следующие упрощенные формулы вычисления необходимых значений:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\vec{X_0} = \frac{\vec{LS}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{SS - 2\vec{X_0}\vec{LS} + N(\vec{X_0})^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{2(N*SS - (\vec{LS})^2)}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{N_1*SS_2 + N_2*SS_1 - 2\vec{LS_1}\vec{LS_2}}{N_1*N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{2((N_1+N_2)(SS_1+SS_2)-(\vec{LS_1}+\vec{LS_2})^2)}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Реализация алгоритма BIRCH состояит из следующих четырёх фаз:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 1&#039;&#039;&#039;. Главной задачей фазы 1 является сканирование всех данных и построение в памяти исходного CF дерева, используя заданное количество памяти. Это дерево стремится отразить информацию о кластеризации данных настолько хорошо, насколько это позволяют ограничения по памяти. При этом плотно распределённые данные группируются в подкластеры, а более разрозненные данные удаляются. После завершения фазы 1 вспомогательные вычисления в дальнейших фазах будут:&lt;br /&gt;
&lt;br /&gt;
1) быстрее, потому что (а) больше не нужны операции ввода-вывода, (b) проблема кластеризации начальных данных упрощается до проблемы кластеризации подкластеров в листьях;&lt;br /&gt;
&lt;br /&gt;
2) точнее, потому что (а) большинство данных с низкой плотностью удалены, (b) оставшиеся данные распределены оптимально (в соответствии с доступным количеством памяти);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 2&#039;&#039;&#039;. Данная фаза является опциональной. Известно, что существующие методы глобальной кластеризации, используемые в рамках фазы 3, имеют различные диапазоны входных значений, при которых их реализация наиболее эффективна. Поэтому потенциально существует пробел между размером фазы 1 и входными значениями фазы 3. И фаза 2 как раз является недостающим связующим звеном: так же как и фаза 1, она сканирует листьевые элементы начального CF дерева для того, чтобы построить меньшее дерево, удаляя ещё больше элементов с низкой плотностью и группируя переполненные подкластеры в большие кластеры.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 3&#039;&#039;&#039;. В данной фазе для листьевых элементов применяется (любой подходящий) алгоритм глобальной кластеризации. Существующие алгоритмы кластеризации наборов точек могут также работать с наборами подкластеров, каждый из которых представлен своим CF вектором. Зная CF вектор, можно вычислить центроид и в дальнейшем заменить всю информацию о кластере этим значением (этого достаточно для вычисления большинства необходимых метрик). После фазы 3 мы получаем набор кластеров, который отражает основные характеристики распределяемых данных.&lt;br /&gt;
Однако, всё ещё могут оставаться некоторые неточности, для устранения которых существует фаза 4.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 4&#039;&#039;&#039;. Данная фаза является опциональной и влечёт за собой затраты на дополнительное сканирование данных для корректировки неточностей и дальнейшего улучшения кластеризации. Фаза 4 использует центроиды кластеров, полученные в фазе 3 для как основы и перераспределяет точки входных данных в ближайшие для них основы для получения нового списка кластеров. Фаза 4, если это необходимо пользователю, может быть расширена дополнительными проходами для уверенности в том, что результат приближается к оптимальному.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Для начала проанализируем вычислительную сложность фазы 1.&lt;br /&gt;
Максимальный размер дерева &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt;. Для того чтобы вставить элемент, мы должны пройти путь от корня до листа (это около &amp;lt;math&amp;gt;1+log_B\frac{M}{P}&amp;lt;/math&amp;gt; узлов). В каждом узле в поисках &amp;quot;ближайшего&amp;quot; нам необходимо просмотреть B элементов; сложность для каждого элемента пропорциональна размерности &#039;&#039;d&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Поэтому сложность вставки всех входных точек &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В случае, когда необходимо перестроить дерево, предположим, что ES - это размер CF элемента. Существует максимум &amp;lt;math&amp;gt;\frac{M}{ES}&amp;lt;/math&amp;gt; листьевых элементов для вставки, поэтому сложность повторной вставки листьевых элементов &amp;lt;math&amp;gt;O(d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Количество итераций перестройки дерева зависит от пороговой величины. На самом деле, это около &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; (двоичное основание появилось из-за того, что мы не можем провести оценку более чем в 2 раза отличающуюся от текущего размера). &amp;lt;math&amp;gt;N_0&amp;lt;/math&amp;gt; - это число входных точек, загруженных в память с пороговым ограничением &amp;lt;math&amp;gt;T_0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Соответственно, итоговая сложность фазы 1 &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P})+log_2\frac{N}{N_0}*d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Анализ фазы 2 проводится аналогично.&lt;br /&gt;
&lt;br /&gt;
Что касается операций ввода-вывода, то в фазе 1 данные сканируются один раз, а в фазе 2 не сканируются вовсе.&lt;br /&gt;
Некоторое количество вычислений связано с удалением точек из областей с низкой плотностью.&lt;br /&gt;
Если количество доступной для этой операции памяти не больше &#039;&#039;M&#039;&#039; и проведено порядка &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; перестроек дерева, то сложность ввода-вывода для фазы 1 существенно не отличается от сложности чтения из файла. Основываясь рассуждениях выше, сложность фаз 1 и 2 будет линейно увеличиваться с ростом N.&lt;br /&gt;
&lt;br /&gt;
В фазе 3 нет операций ввода-вывода. Её сложность ограничена константой, которая зависит от максимального размера входных данных, и варианта выбранного алгоритма для кластеризации. &lt;br /&gt;
&lt;br /&gt;
Фаза 4 снова сканирует данные и записывает каждую точку в подходящий кластер; время работы пропорционально &amp;lt;math&amp;gt;N*K&amp;lt;/math&amp;gt;.   &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Достоинства алгоритма ===&lt;br /&gt;
По сравнению с предыдущими методами BIRCH обладает следующими достоинствами:&lt;br /&gt;
&lt;br /&gt;
1. BIRCH является локальным алгоритмом, то есть каждое решение о каждом элементе кластера принимается без повторного сканирования данных или уже существующих кластеров. Используются только метрики, отражающие близость элементов друг к другу.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH использует факт неравномерного распределения данных в пространстве и поэтому не все данные рассматриваются как одинаково важные для построения кластера. Области с большой плотностью обрабатываются как единый кластер. Данные в более разреженных областях могут удаляться (опционально).&lt;br /&gt;
&lt;br /&gt;
3. BIRCH использует всю доступную память для получения наилучших из возможных подкластеров, в то же время минимизируя затраты на операции ввода/вывода. Оптимизация процесса кластеризации достигается за счет использования взвешенно-сбалансированного дерева. При этом время исполнения линейно.&lt;br /&gt;
&lt;br /&gt;
4. BIRCH не требует всего набора данных заранее (при этом просматривает его всего один раз).&lt;br /&gt;
&lt;br /&gt;
=== Недостатки алгоритма ===&lt;br /&gt;
&lt;br /&gt;
1. Алгоритм позволяет работать только с числовыми данными.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH хорошо выделяет только кластеры сферической формы.&lt;br /&gt;
&lt;br /&gt;
3. Существует необходимость в задании пороговых значений.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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;/div&gt;</summary>
		<author><name>Светлана Морозова</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13524</id>
		<title>Участник:Smirnov.maxim/BIRCH</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13524"/>
		<updated>2016-10-23T16:15:23Z</updated>

		<summary type="html">&lt;p&gt;Светлана Морозова: /* ЧАСТЬ. Программная реализация алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Нахождение полезных для анализа закономерностей в больших объёмах данных с недавних пор вызывает значительный интерес. В связи с этим ввелось и стало активно развиваться такое понятие как &#039;&#039;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7 кластеризация]&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Ранние работы и алгоритмы, разработанные в этой области, не уделяли достаточного внимания анализу очень больших наборов данных или минимизации издержек на процессы ввода-вывода.&lt;br /&gt;
Решением этих проблем стал алгоритм, известный как BIRCH.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIRCH&#039;&#039;&#039; (balanced iterative reducing and clustering using hierarchies)- алгоритм, применяемый в области [https://ru.wikipedia.org/wiki/Data_mining Data mining] и использующий принципы [https://ru.wikipedia.org/wiki/%D0%98%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F иерархической кластеризации].&lt;br /&gt;
&lt;br /&gt;
Если имеется очень большой набор данных, то в пространстве он распределен, как правило, неравномерно. Кластерный анализ определяет места наибольшего и наименьшего скоплений, чтобы таким образом понять всю картину целиком. Кроме того, полученные кластеры визуализируются гораздо нагляднее, чем начальные &amp;quot;сырые&amp;quot; данные.&lt;br /&gt;
Задачей алгоритмов кластеризации является не только простое разбиение данных на кластеры, но и работа в рамках ограниченного объёма доступной памяти (как правило, её объём гораздо меньше, чем размер исходного набора данных) и минимизация времени, требуемого на операции ввода-вывода.&lt;br /&gt;
&lt;br /&gt;
Для наилучшего решения этих проблем BIRCH распределяет входящие данные по кластерам динамически. Для эффективной кластеризации алгоритму требуется всего одно сканирование данных (т.е. с увеличением количества данных сложность увеличивается линейно). А при помощи одной (или более) дополнительных итераций можно и далее улучшать эффективность. BIRCH также является первым алгоритмом, предложенным для эффективного управления &amp;quot;шумами&amp;quot; (данными, которые не вписываются в общее представление модели).&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Теоретическая основа ===&lt;br /&gt;
&lt;br /&gt;
Пусть в кластере имеются &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}, i=1,2,...,N&amp;lt;/math&amp;gt;.&lt;br /&gt;
Тогда &#039;&#039;&#039;центроид&#039;&#039;&#039; &amp;lt;math&amp;gt;{\vec{{X_0}}}&amp;lt;/math&amp;gt;, &#039;&#039;&#039;радиус&#039;&#039;&#039; &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &#039;&#039;&#039;диаметр&#039;&#039;&#039; &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластера определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;{\vec{X_0}}=\frac{\sum_{i=1}^N\vec{X_i}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{\sum_{i=1}^N{(\vec{X_i} - \vec{X_0})}^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{\sum_{i=1}^N\sum_{j=1}^N{(\vec{X_i} - \vec{X_j})}^2}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; - это среднее расстояние от каждой точки до центроида. &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; - это среднее расстояние между парами в кластере. Данные величины являются альтернативными метриками плотности кластера относительно центроида.&lt;br /&gt;
&lt;br /&gt;
Для измерения близости друг к другу двух кластеров вводятся следующие метрики:&lt;br /&gt;
&lt;br /&gt;
пусть даны центроиды двух кластеров &amp;lt;math&amp;gt;\vec{X_{01}}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\vec{X_{02}}&amp;lt;/math&amp;gt;.&lt;br /&gt;
Евклидова метрика &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt; и метрика Манхэттена &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt; между двумя кластерами определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_0 = ((\vec{X_{01}}-\vec{X_{02}})^2)^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_1 = |\vec{X_{01}}-\vec{X_{02}}| = \sum_{i=1}^d |{\vec{X_{01}}}^{(i)}-{\vec{X_{02}}}^{(i)}| &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть имеются два кластера, содержащих соответственно  &amp;lt;math&amp;gt;N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;N_2&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i= 1,2, ...,N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\{\vec{X_j}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j= N_1+1,N_1+2, ...,N_1+N_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Среднее расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &#039;&#039;&#039;среднее внутрикластерное расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &#039;&#039;&#039;дисперсия&#039;&#039;&#039; &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; для двух кластеров определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{\sum_{i=1}^{N_1}\sum_{j=N_1+1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{N_1N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{\sum_{i=1}^{N_1+N_2}\sum_{j=1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_4 = \sum_{k=1}^{N_1+N_2}(\vec{X_k} - \frac{\sum_{i=1}^{N_1+N_2}\vec{X_i}}{N_1+N_2})^2 - \sum_{i=1}^{N_1}(\vec{X_i} - \frac{\sum_{i=1}^{N_1}\vec{X_i}}{N_1})^2 - \sum_{j=N_1+1}^{N_1+N_2}(\vec{X_j} - \frac{\sum_{i=N_1+1}^{N_1+N_2}\vec{X_i}}{N_2})^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Таким образом, величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; относятся к отдельным кластерам, а &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; - к объединению двух кластеров.&lt;br /&gt;
&lt;br /&gt;
=== Кластерный элемент и кластерное дерево ===&lt;br /&gt;
&lt;br /&gt;
В основе концепции алгоритма BIRCH лежат понятия &#039;&#039;&#039;кластерного элемента&#039;&#039;&#039; и &#039;&#039;&#039;кластерного дерева (CF Tree)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====Кластерный элемент ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; Пусть в кластере содержатся  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности  &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;:&amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;i=1,2,...,N&amp;lt;/math&amp;gt;. &lt;br /&gt;
&#039;&#039;&#039;Кластерный элемент (CF)&#039;&#039;&#039; - тройка чисел, характеризующая информацию о кластере: &lt;br /&gt;
&amp;lt;math&amp;gt;CF = (N, \vec{LS}, SS)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - количество элементов входных данных, содержащихся в кластере, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; - линейная сумма входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}\vec{X_i}&amp;lt;/math&amp;gt;), &amp;lt;math&amp;gt;SS&amp;lt;/math&amp;gt; - сумма квадратов входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}{\vec{X_i}}^2&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Теорема&#039;&#039;&#039; Пусть &amp;lt;math&amp;gt;CF_1 = (N_1, \vec{LS_1}, SS_1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;CF_2 = (N_1, \vec{LS_2}, SS_2)&amp;lt;/math&amp;gt; - CF векторы двух непересекающихся кластеров. Тогда при их объединении образуется кластер со следующим CF вектором: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF = CF_1 + CF_2 = (N_1+N_2, \vec{LS_1}+\vec{LS_2}, SS_1+SS_2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Из указанных выше определения и теоремы вытекает тот факт, что при объединении кластеров их CF вектор может вычисляться инкрементно и точно. &lt;br /&gt;
Легко показать, что вычислить величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;, как и обычные метрики, также не составит труда.&lt;br /&gt;
&lt;br /&gt;
Таким образом, в данном случае информацией о кластере является не весь набор точек, а вектор CF. Хранение одного только вектора может показаться неэффективным, но этого вполне достаточно для оперирования всеми необходимыми метриками, на основе которых принимаются решения в алгоритме BIRCH.&lt;br /&gt;
&lt;br /&gt;
==== Кластерное дерево ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; &#039;&#039;&#039;Кластерное дерево (CF Tree)&#039;&#039;&#039; - это взвешенно сбалансированное дерево с двумя параметрами: &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - коэффициент разветвления, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - пороговая величина. Каждый нелистьевой узел дерева имеет не более чем &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; вхождений узлов следующей формы: &amp;lt;math&amp;gt;[CF_i,child_i]&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i=1,2,...,B&amp;lt;/math&amp;gt;, &#039;&#039;child&#039;&#039; - указатель на i-й дочерний узел, &amp;lt;math&amp;gt;CF_i&amp;lt;/math&amp;gt; - CF вектор соответствующего подкластера.&lt;br /&gt;
&lt;br /&gt;
Каждый листьевой узел имеет ссылку на два соседних узла (&#039;&#039;prev&#039;&#039; и &#039;&#039;next&#039;&#039;) для того, чтобы связать все узлы для эффективного сканирования.&lt;br /&gt;
Все листьевые узлы должны удовлетворять пороговому ограничению &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, т.е. диаметр (радиус) не должен превосходить &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;.&lt;br /&gt;
В процессе вставки новых данных CF дерево строится динамически. Оно использует вставку данных для кластеризации точно также как &amp;lt;math&amp;gt;B+&amp;lt;/math&amp;gt; [https://ru.wikipedia.org/wiki/B%2B-%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE дерево] использует её для поиска.&lt;br /&gt;
CF дерево очень компактно, поскольку каждый листьевой узел - это не просто точка, а подкластер (который объединяет множество точек с учётом ограничения &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Операция вставки в &#039;&#039;&#039;CF&#039;&#039;&#039; дерево ====&lt;br /&gt;
&lt;br /&gt;
Опишем алгоритм вставки элемнта &amp;lt;math&amp;gt;Ent&amp;lt;/math&amp;gt; в CF дерево:&lt;br /&gt;
&lt;br /&gt;
1) &#039;&#039;Определение подходящего листа&#039;&#039;: Начиная с корня, алгоритм рекурсивно спускается по CF дереву, выбирая &#039;&#039;&#039;ближайший&#039;&#039;&#039; дочерний узел в соответствии с выбранной метрикой &amp;lt;math&amp;gt;D0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D4&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &#039;&#039;Преобразование листа&#039;&#039;: Когда алгоритм доходит до листа, он находит ближайшую листьевой элемент, скажем, &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;, а затем проверяет, можно ли добавить &#039;&#039;Ent&#039;&#039; к &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt; без нарушения порогового условия. Если да, то с учётом этого изменяется CF вектор для &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;; если нет, то &#039;&#039;Ent&#039;&#039; становится новым элементом листа. Если в листе для этого достаточно места, то шаг окончен, иначе он должен &amp;quot;расщепиться&amp;quot;. Расщепление узла производится при помощи выбора за основу наиболее удалённой друг от друга пары элементов и перераспределение оставшихся элементов в соответствии с выбранным критерием близости.&lt;br /&gt;
&lt;br /&gt;
3) &#039;&#039;Преобразование пути к листу&#039;&#039;: После вставки &#039;&#039;Ent&#039;&#039; в лист мы должны обновить информацию о CF для каждого нелистьевого элемента на пути к листу. При отсутствии расщепления это означает простое сложение CF векторов для отражения факта добавления &#039;&#039;Ent&#039;&#039;. Расщепление листа же требует вставки нового нелистьевого элемента в родительский узел для задания только что созданного листа. Если у родителя есть место для этого элемента, то необходимо просто преобразовать CF векторы на всех более высоких уровнях. В общем случае, однако, нам также придётся расщепить родительский узел, и так далее до корня. Если расщеплён корень, то высота дерева увеличивается на единицу.&lt;br /&gt;
&lt;br /&gt;
4) &#039;&#039;Улучшение слияния&#039;&#039;: Расщепление вызвано ограничением на размер узла, который не зависит от кластеризационных свойств данных. Если во входящем потоке присутствуют &amp;quot;искажённые&amp;quot; (из областей с низкой плотностью) данные, это может повлиять на качество кластеризации, а также уменьшить эффективность использования памяти. Дополнительный шаг алгоритма помогает решить эти проблемы: предположим, что произошло расщепление листа, и распространение этого процесса остановилось на некотором нелистьевом узле &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt;, то есть &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; может вместить дополнительный элемент, полученный после расщепления. Теперь мы сканируем узел &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; для нахождения двух наиболее близких элементов. Если это не пара, отвечающая расщеплению, мы пытаемся объединить их и поставить в соответствие два дочерних узла. Если количество элементов в дочерних узлах  больше B, мы снова расщепляем результат объединения.&lt;br /&gt;
В процессе повторного расщепления, в случае, если один источник собирает достаточно элементов для того, чтобы полностью заполнить узел, оставшиеся элементы передаются другом источнику. В итоге, если объединённые элементы помещаются в одном узле, в нём освобождается место для ещё одного элемента. Тем самым увеличивается степень использования свободного пространства и откладывается дальнейшее расщепление. В ином случае мы улучшаем распределение элементов в двух ближайших подкластерах.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро алгоритма заключается в многократном выполнении операции вставки нового элемента в дерево, в процессе чего требуется вычисление следующих величин:&lt;br /&gt;
&lt;br /&gt;
* радиуса &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; или диаметра &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластерного элемента. Выполняется при попытке вставить новый элемент в один из подкластеров листьевого узла дерева.&lt;br /&gt;
&lt;br /&gt;
* расстояния между двумя элементами. Выполняется при поиске ближайшего по отношению к новому элементу подкластера в узле дерева по одной из рассмотренных в разд. 1.2.1 метрик &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Зная характеристики кластерных элементов &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;, в результате алгебраических преобразований можно получить следующие упрощенные формулы вычисления необходимых значений:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\vec{X_0} = \frac{\vec{LS}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{SS - 2\vec{X_0}\vec{LS} + N(\vec{X_0})^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{2(N*SS - (\vec{LS})^2)}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{N_1*SS_2 + N_2*SS_1 - 2\vec{LS_1}\vec{LS_2}}{N_1*N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{2((N_1+N_2)(SS_1+SS_2)-(\vec{LS_1}+\vec{LS_2})^2)}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Реализация алгоритма BIRCH состояит из следующих четырёх фаз:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 1&#039;&#039;&#039;. Главной задачей фазы 1 является сканирование всех данных и построение в памяти исходного CF дерева, используя заданное количество памяти. Это дерево стремится отразить информацию о кластеризации данных настолько хорошо, насколько это позволяют ограничения по памяти. При этом плотно распределённые данные группируются в подкластеры, а более разрозненные данные удаляются. После завершения фазы 1 вспомогательные вычисления в дальнейших фазах будут:&lt;br /&gt;
&lt;br /&gt;
1) быстрее, потому что (а) больше не нужны операции ввода-вывода, (b) проблема кластеризации начальных данных упрощается до проблемы кластеризации подкластеров в листьях;&lt;br /&gt;
&lt;br /&gt;
2) точнее, потому что (а) большинство данных с низкой плотностью удалены, (b) оставшиеся данные распределены оптимально (в соответствии с доступным количеством памяти);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 2&#039;&#039;&#039;. Данная фаза является опциональной. Известно, что существующие методы глобальной кластеризации, используемые в рамках фазы 3, имеют различные диапазоны входных значений, при которых их реализация наиболее эффективна. Поэтому потенциально существует пробел между размером фазы 1 и входными значениями фазы 3. И фаза 2 как раз является недостающим связующим звеном: так же как и фаза 1, она сканирует листьевые элементы начального CF дерева для того, чтобы построить меньшее дерево, удаляя ещё больше элементов с низкой плотностью и группируя переполненные подкластеры в большие кластеры.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 3&#039;&#039;&#039;. В данной фазе для листьевых элементов применяется (любой подходящий) алгоритм глобальной кластеризации. Существующие алгоритмы кластеризации наборов точек могут также работать с наборами подкластеров, каждый из которых представлен своим CF вектором. Зная CF вектор, можно вычислить центроид и в дальнейшем заменить всю информацию о кластере этим значением (этого достаточно для вычисления большинства необходимых метрик). После фазы 3 мы получаем набор кластеров, который отражает основные характеристики распределяемых данных.&lt;br /&gt;
Однако, всё ещё могут оставаться некоторые неточности, для устранения которых существует фаза 4.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 4&#039;&#039;&#039;. Данная фаза является опциональной и влечёт за собой затраты на дополнительное сканирование данных для корректировки неточностей и дальнейшего улучшения кластеризации. Фаза 4 использует центроиды кластеров, полученные в фазе 3 для как основы и перераспределяет точки входных данных в ближайшие для них основы для получения нового списка кластеров. Фаза 4, если это необходимо пользователю, может быть расширена дополнительными проходами для уверенности в том, что результат приближается к оптимальному.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Для начала проанализируем вычислительную сложность фазы 1.&lt;br /&gt;
Максимальный размер дерева &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt;. Для того чтобы вставить элемент, мы должны пройти путь от корня до листа (это около &amp;lt;math&amp;gt;1+log_B\frac{M}{P}&amp;lt;/math&amp;gt; узлов). В каждом узле в поисках &amp;quot;ближайшего&amp;quot; нам необходимо просмотреть B элементов; сложность для каждого элемента пропорциональна размерности &#039;&#039;d&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Поэтому сложность вставки всех входных точек &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В случае, когда необходимо перестроить дерево, предположим, что ES - это размер CF элемента. Существует максимум &amp;lt;math&amp;gt;\frac{M}{ES}&amp;lt;/math&amp;gt; листьевых элементов для вставки, поэтому сложность повторной вставки листьевых элементов &amp;lt;math&amp;gt;O(d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Количество итераций перестройки дерева зависит от пороговой величины. На самом деле, это около &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; (двоичное основание появилось из-за того, что мы не можем провести оценку более чем в 2 раза отличающуюся от текущего размера). &amp;lt;math&amp;gt;N_0&amp;lt;/math&amp;gt; - это число входных точек, загруженных в память с пороговым ограничением &amp;lt;math&amp;gt;T_0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Соответственно, итоговая сложность фазы 1 &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P})+log_2\frac{N}{N_0}*d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Анализ фазы 2 проводится аналогично.&lt;br /&gt;
&lt;br /&gt;
Что касается операций ввода-вывода, то в фазе 1 данные сканируются один раз, а в фазе 2 не сканируются вовсе.&lt;br /&gt;
Некоторое количество вычислений связано с удалением точек из областей с низкой плотностью.&lt;br /&gt;
Если количество доступной для этой операции памяти не больше &#039;&#039;M&#039;&#039; и проведено порядка &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; перестроек дерева, то сложность ввода-вывода для фазы 1 существенно не отличается от сложности чтения из файла. Основываясь рассуждениях выше, сложность фаз 1 и 2 будет линейно увеличиваться с ростом N.&lt;br /&gt;
&lt;br /&gt;
В фазе 3 нет операций ввода-вывода. Её сложность ограничена константой, которая зависит от максимального размера входных данных, и варианта выбранного алгоритма для кластеризации. &lt;br /&gt;
&lt;br /&gt;
Фаза 4 снова сканирует данные и записывает каждую точку в подходящий кластер; время работы пропорционально &amp;lt;math&amp;gt;N*K&amp;lt;/math&amp;gt;.   &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Достоинства алгоритма ===&lt;br /&gt;
По сравнению с предыдущими методами BIRCH обладает следующими достоинствами:&lt;br /&gt;
&lt;br /&gt;
1. BIRCH является локальным алгоритмом, то есть каждое решение о каждом элементе кластера принимается без повторного сканирования данных или уже существующих кластеров. Используются только метрики, отражающие близость элементов друг к другу.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH использует факт неравномерного распределения данных в пространстве и поэтому не все данные рассматриваются как одинаково важные для построения кластера. Области с большой плотностью обрабатываются как единый кластер. Данные в более разреженных областях могут удаляться (опционально).&lt;br /&gt;
&lt;br /&gt;
3. BIRCH использует всю доступную память для получения наилучших из возможных подкластеров, в то же время минимизируя затраты на операции ввода/вывода. Оптимизация процесса кластеризации достигается за счет использования взвешенно-сбалансированного дерева. При этом время исполнения линейно.&lt;br /&gt;
&lt;br /&gt;
4. BIRCH не требует всего набора данных заранее (при этом просматривает его всего один раз).&lt;br /&gt;
&lt;br /&gt;
=== Недостатки алгоритма ===&lt;br /&gt;
&lt;br /&gt;
1. Алгоритм позволяет работать только с числовыми данными.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH хорошо выделяет только кластеры сферической формы.&lt;br /&gt;
&lt;br /&gt;
3. Существует необходимость в задании пороговых значений.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Локальность данных и вычислений ==&lt;br /&gt;
&lt;br /&gt;
== Возможные способы и особенности параллельной реализации алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Масштабируемость алгоритма и его реализации ==&lt;br /&gt;
&lt;br /&gt;
== Динамические характеристики и эффективность реализации алгоритма ==&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;/div&gt;</summary>
		<author><name>Светлана Морозова</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13499</id>
		<title>Участник:Smirnov.maxim/BIRCH</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13499"/>
		<updated>2016-10-23T09:37:43Z</updated>

		<summary type="html">&lt;p&gt;Светлана Морозова: /* Недостатки алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Нахождение полезных для анализа закономерностей в больших объёмах данных с недавних пор вызывает значительный интерес. В связи с этим ввелось и стало активно развиваться такое понятие как &#039;&#039;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7 кластеризация]&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Ранние работы и алгоритмы, разработанные в этой области, не уделяли достаточного внимания анализу очень больших наборов данных или минимизации издержек на процессы ввода-вывода.&lt;br /&gt;
Решением этих проблем стал алгоритм, известный как BIRCH.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIRCH&#039;&#039;&#039; (balanced iterative reducing and clustering using hierarchies)- алгоритм, применяемый в области [https://ru.wikipedia.org/wiki/Data_mining Data mining] и использующий принципы [https://ru.wikipedia.org/wiki/%D0%98%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F иерархической кластеризации].&lt;br /&gt;
&lt;br /&gt;
Если имеется очень большой набор данных, то в пространстве он распределен, как правило, неравномерно. Кластерный анализ определяет места наибольшего и наименьшего скоплений, чтобы таким образом понять всю картину целиком. Кроме того, полученные кластеры визуализируются гораздо нагляднее, чем начальные &amp;quot;сырые&amp;quot; данные.&lt;br /&gt;
Задачей алгоритмов кластеризации является не только простое разбиение данных на кластеры, но и работа в рамках ограниченного объёма доступной памяти (как правило, её объём гораздо меньше, чем размер исходного набора данных) и минимизация времени, требуемого на операции ввода-вывода.&lt;br /&gt;
&lt;br /&gt;
Для наилучшего решения этих проблем BIRCH распределяет входящие данные по кластерам динамически. Для эффективной кластеризации алгоритму требуется всего одно сканирование данных (т.е. с увеличением количества данных сложность увеличивается линейно). А при помощи одной (или более) дополнительных итераций можно и далее улучшать эффективность. BIRCH также является первым алгоритмом, предложенным для эффективного управления &amp;quot;шумами&amp;quot; (данными, которые не вписываются в общее представление модели).&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Теоретическая основа ===&lt;br /&gt;
&lt;br /&gt;
Пусть в кластере имеются &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}, i=1,2,...,N&amp;lt;/math&amp;gt;.&lt;br /&gt;
Тогда &#039;&#039;&#039;центроид&#039;&#039;&#039; &amp;lt;math&amp;gt;{\vec{{X_0}}}&amp;lt;/math&amp;gt;, &#039;&#039;&#039;радиус&#039;&#039;&#039; &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &#039;&#039;&#039;диаметр&#039;&#039;&#039; &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластера определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;{\vec{X_0}}=\frac{\sum_{i=1}^N\vec{X_i}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{\sum_{i=1}^N{(\vec{X_i} - \vec{X_0})}^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{\sum_{i=1}^N\sum_{j=1}^N{(\vec{X_i} - \vec{X_j})}^2}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; - это среднее расстояние от каждой точки до центроида. &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; - это среднее расстояние между парами в кластере. Данные величины являются альтернативными метриками плотности кластера относительно центроида.&lt;br /&gt;
&lt;br /&gt;
Для измерения близости друг к другу двух кластеров вводятся следующие метрики:&lt;br /&gt;
&lt;br /&gt;
пусть даны центроиды двух кластеров &amp;lt;math&amp;gt;\vec{X_{01}}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\vec{X_{02}}&amp;lt;/math&amp;gt;.&lt;br /&gt;
Евклидова метрика &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt; и метрика Манхэттена &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt; между двумя кластерами определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_0 = ((\vec{X_{01}}-\vec{X_{02}})^2)^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_1 = |\vec{X_{01}}-\vec{X_{02}}| = \sum_{i=1}^d |{\vec{X_{01}}}^{(i)}-{\vec{X_{02}}}^{(i)}| &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть имеются два кластера, содержащих соответственно  &amp;lt;math&amp;gt;N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;N_2&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i= 1,2, ...,N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\{\vec{X_j}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j= N_1+1,N_1+2, ...,N_1+N_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Среднее расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &#039;&#039;&#039;среднее внутрикластерное расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &#039;&#039;&#039;дисперсия&#039;&#039;&#039; &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; для двух кластеров определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{\sum_{i=1}^{N_1}\sum_{j=N_1+1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{N_1N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{\sum_{i=1}^{N_1+N_2}\sum_{j=1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_4 = \sum_{k=1}^{N_1+N_2}(\vec{X_k} - \frac{\sum_{i=1}^{N_1+N_2}\vec{X_i}}{N_1+N_2})^2 - \sum_{i=1}^{N_1}(\vec{X_i} - \frac{\sum_{i=1}^{N_1}\vec{X_i}}{N_1})^2 - \sum_{j=N_1+1}^{N_1+N_2}(\vec{X_j} - \frac{\sum_{i=N_1+1}^{N_1+N_2}\vec{X_i}}{N_2})^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Таким образом, величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; относятся к отдельным кластерам, а &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; - к объединению двух кластеров.&lt;br /&gt;
&lt;br /&gt;
=== Кластерный элемент и кластерное дерево ===&lt;br /&gt;
&lt;br /&gt;
В основе концепции алгоритма BIRCH лежат понятия &#039;&#039;&#039;кластерного элемента&#039;&#039;&#039; и &#039;&#039;&#039;кластерного дерева (CF Tree)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====Кластерный элемент ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; Пусть в кластере содержатся  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности  &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;:&amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;i=1,2,...,N&amp;lt;/math&amp;gt;. &lt;br /&gt;
&#039;&#039;&#039;Кластерный элемент (CF)&#039;&#039;&#039; - тройка чисел, характеризующая информацию о кластере: &lt;br /&gt;
&amp;lt;math&amp;gt;CF = (N, \vec{LS}, SS)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - количество элементов входных данных, содержащихся в кластере, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; - линейная сумма входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}\vec{X_i}&amp;lt;/math&amp;gt;), &amp;lt;math&amp;gt;SS&amp;lt;/math&amp;gt; - сумма квадратов входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}{\vec{X_i}}^2&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Теорема&#039;&#039;&#039; Пусть &amp;lt;math&amp;gt;CF_1 = (N_1, \vec{LS_1}, SS_1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;CF_2 = (N_1, \vec{LS_2}, SS_2)&amp;lt;/math&amp;gt; - CF векторы двух непересекающихся кластеров. Тогда при их объединении образуется кластер со следующим CF вектором: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF = CF_1 + CF_2 = (N_1+N_2, \vec{LS_1}+\vec{LS_2}, SS_1+SS_2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Из указанных выше определения и теоремы вытекает тот факт, что при объединении кластеров их CF вектор может вычисляться инкрементно и точно. &lt;br /&gt;
Легко показать, что вычислить величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;, как и обычные метрики, также не составит труда.&lt;br /&gt;
&lt;br /&gt;
Таким образом, в данном случае информацией о кластере является не весь набор точек, а вектор CF. Хранение одного только вектора может показаться неэффективным, но этого вполне достаточно для оперирования всеми необходимыми метриками, на основе которых принимаются решения в алгоритме BIRCH.&lt;br /&gt;
&lt;br /&gt;
==== Кластерное дерево ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; &#039;&#039;&#039;Кластерное дерево (CF Tree)&#039;&#039;&#039; - это взвешенно сбалансированное дерево с двумя параметрами: &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - коэффициент разветвления, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - пороговая величина. Каждый нелистьевой узел дерева имеет не более чем &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; вхождений узлов следующей формы: &amp;lt;math&amp;gt;[CF_i,child_i]&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i=1,2,...,B&amp;lt;/math&amp;gt;, &#039;&#039;child&#039;&#039; - указатель на i-й дочерний узел, &amp;lt;math&amp;gt;CF_i&amp;lt;/math&amp;gt; - CF вектор соответствующего подкластера.&lt;br /&gt;
&lt;br /&gt;
Каждый листьевой узел имеет ссылку на два соседних узла (&#039;&#039;prev&#039;&#039; и &#039;&#039;next&#039;&#039;) для того, чтобы связать все узлы для эффективного сканирования.&lt;br /&gt;
Все листьевые узлы должны удовлетворять пороговому ограничению &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, т.е. диаметр (радиус) не должен превосходить &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;.&lt;br /&gt;
В процессе вставки новых данных CF дерево строится динамически. Оно использует вставку данных для кластеризации точно также как &amp;lt;math&amp;gt;B+&amp;lt;/math&amp;gt; [https://ru.wikipedia.org/wiki/B%2B-%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE дерево] использует её для поиска.&lt;br /&gt;
CF дерево очень компактно, поскольку каждый листьевой узел - это не просто точка, а подкластер (который объединяет множество точек с учётом ограничения &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Операция вставки в &#039;&#039;&#039;CF&#039;&#039;&#039; дерево ====&lt;br /&gt;
&lt;br /&gt;
Опишем алгоритм вставки элемнта &amp;lt;math&amp;gt;Ent&amp;lt;/math&amp;gt; в CF дерево:&lt;br /&gt;
&lt;br /&gt;
1) &#039;&#039;Определение подходящего листа&#039;&#039;: Начиная с корня, алгоритм рекурсивно спускается по CF дереву, выбирая &#039;&#039;&#039;ближайший&#039;&#039;&#039; дочерний узел в соответствии с выбранной метрикой &amp;lt;math&amp;gt;D0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D4&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &#039;&#039;Преобразование листа&#039;&#039;: Когда алгоритм доходит до листа, он находит ближайшую листьевой элемент, скажем, &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;, а затем проверяет, можно ли добавить &#039;&#039;Ent&#039;&#039; к &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt; без нарушения порогового условия. Если да, то с учётом этого изменяется CF вектор для &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;; если нет, то &#039;&#039;Ent&#039;&#039; становится новым элементом листа. Если в листе для этого достаточно места, то шаг окончен, иначе он должен &amp;quot;расщепиться&amp;quot;. Расщепление узла производится при помощи выбора за основу наиболее удалённой друг от друга пары элементов и перераспределение оставшихся элементов в соответствии с выбранным критерием близости.&lt;br /&gt;
&lt;br /&gt;
3) &#039;&#039;Преобразование пути к листу&#039;&#039;: После вставки &#039;&#039;Ent&#039;&#039; в лист мы должны обновить информацию о CF для каждого нелистьевого элемента на пути к листу. При отсутствии расщепления это означает простое сложение CF векторов для отражения факта добавления &#039;&#039;Ent&#039;&#039;. Расщепление листа же требует вставки нового нелистьевого элемента в родительский узел для задания только что созданного листа. Если у родителя есть место для этого элемента, то необходимо просто преобразовать CF векторы на всех более высоких уровнях. В общем случае, однако, нам также придётся расщепить родительский узел, и так далее до корня. Если расщеплён корень, то высота дерева увеличивается на единицу.&lt;br /&gt;
&lt;br /&gt;
4) &#039;&#039;Улучшение слияния&#039;&#039;: Расщепление вызвано ограничением на размер узла, который не зависит от кластеризационных свойств данных. Если во входящем потоке присутствуют &amp;quot;искажённые&amp;quot; (из областей с низкой плотностью) данные, это может повлиять на качество кластеризации, а также уменьшить эффективность использования памяти. Дополнительный шаг алгоритма помогает решить эти проблемы: предположим, что произошло расщепление листа, и распространение этого процесса остановилось на некотором нелистьевом узле &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt;, то есть &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; может вместить дополнительный элемент, полученный после расщепления. Теперь мы сканируем узел &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; для нахождения двух наиболее близких элементов. Если это не пара, отвечающая расщеплению, мы пытаемся объединить их и поставить в соответствие два дочерних узла. Если количество элементов в дочерних узлах  больше B, мы снова расщепляем результат объединения.&lt;br /&gt;
В процессе повторного расщепления, в случае, если один источник собирает достаточно элементов для того, чтобы полностью заполнить узел, оставшиеся элементы передаются другом источнику. В итоге, если объединённые элементы помещаются в одном узле, в нём освобождается место для ещё одного элемента. Тем самым увеличивается степень использования свободного пространства и откладывается дальнейшее расщепление. В ином случае мы улучшаем распределение элементов в двух ближайших подкластерах.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро алгоритма заключается в многократном выполнении операции вставки нового элемента в дерево, в процессе чего требуется вычисление следующих величин:&lt;br /&gt;
&lt;br /&gt;
* радиуса &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; или диаметра &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластерного элемента. Выполняется при попытке вставить новый элемент в один из подкластеров листьевого узла дерева.&lt;br /&gt;
&lt;br /&gt;
* расстояния между двумя элементами. Выполняется при поиске ближайшего по отношению к новому элементу подкластера в узле дерева по одной из рассмотренных в разд. 1.2.1 метрик &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Зная характеристики кластерных элементов &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;, в результате алгебраических преобразований можно получить следующие упрощенные формулы вычисления необходимых значений:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\vec{X_0} = \frac{\vec{LS}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{SS - 2\vec{X_0}\vec{LS} + N(\vec{X_0})^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{2(N*SS - (\vec{LS})^2)}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{N_1*SS_2 + N_2*SS_1 - 2\vec{LS_1}\vec{LS_2}}{N_1*N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{2((N_1+N_2)(SS_1+SS_2)-(\vec{LS_1}+\vec{LS_2})^2)}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Реализация алгоритма BIRCH состояит из следующих четырёх фаз:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 1&#039;&#039;&#039;. Главной задачей фазы 1 является сканирование всех данных и построение в памяти исходного CF дерева, используя заданное количество памяти. Это дерево стремится отразить информацию о кластеризации данных настолько хорошо, насколько это позволяют ограничения по памяти. При этом плотно распределённые данные группируются в подкластеры, а более разрозненные данные удаляются. После завершения фазы 1 вспомогательные вычисления в дальнейших фазах будут:&lt;br /&gt;
&lt;br /&gt;
1) быстрее, потому что (а) больше не нужны операции ввода-вывода, (b) проблема кластеризации начальных данных упрощается до проблемы кластеризации подкластеров в листьях;&lt;br /&gt;
&lt;br /&gt;
2) точнее, потому что (а) большинство данных с низкой плотностью удалены, (b) оставшиеся данные распределены оптимально (в соответствии с доступным количеством памяти);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 2&#039;&#039;&#039;. Данная фаза является опциональной. Известно, что существующие методы глобальной кластеризации, используемые в рамках фазы 3, имеют различные диапазоны входных значений, при которых их реализация наиболее эффективна. Поэтому потенциально существует пробел между размером фазы 1 и входными значениями фазы 3. И фаза 2 как раз является недостающим связующим звеном: так же как и фаза 1, она сканирует листьевые элементы начального CF дерева для того, чтобы построить меньшее дерево, удаляя ещё больше элементов с низкой плотностью и группируя переполненные подкластеры в большие кластеры.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 3&#039;&#039;&#039;. В данной фазе для листьевых элементов применяется (любой подходящий) алгоритм глобальной кластеризации. Существующие алгоритмы кластеризации наборов точек могут также работать с наборами подкластеров, каждый из которых представлен своим CF вектором. Зная CF вектор, можно вычислить центроид и в дальнейшем заменить всю информацию о кластере этим значением (этого достаточно для вычисления большинства необходимых метрик). После фазы 3 мы получаем набор кластеров, который отражает основные характеристики распределяемых данных.&lt;br /&gt;
Однако, всё ещё могут оставаться некоторые неточности, для устранения которых существует фаза 4.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 4&#039;&#039;&#039;. Данная фаза является опциональной и влечёт за собой затраты на дополнительное сканирование данных для корректировки неточностей и дальнейшего улучшения кластеризации. Фаза 4 использует центроиды кластеров, полученные в фазе 3 для как основы и перераспределяет точки входных данных в ближайшие для них основы для получения нового списка кластеров. Фаза 4, если это необходимо пользователю, может быть расширена дополнительными проходами для уверенности в том, что результат приближается к оптимальному.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Для начала проанализируем вычислительную сложность фазы 1.&lt;br /&gt;
Максимальный размер дерева &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt;. Для того чтобы вставить элемент, мы должны пройти путь от корня до листа (это около &amp;lt;math&amp;gt;1+log_B\frac{M}{P}&amp;lt;/math&amp;gt; узлов). В каждом узле в поисках &amp;quot;ближайшего&amp;quot; нам необходимо просмотреть B элементов; сложность для каждого элемента пропорциональна размерности &#039;&#039;d&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Поэтому сложность вставки всех входных точек &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В случае, когда необходимо перестроить дерево, предположим, что ES - это размер CF элемента. Существует максимум &amp;lt;math&amp;gt;\frac{M}{ES}&amp;lt;/math&amp;gt; листьевых элементов для вставки, поэтому сложность повторной вставки листьевых элементов &amp;lt;math&amp;gt;O(d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Количество итераций перестройки дерева зависит от пороговой величины. На самом деле, это около &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; (двоичное основание появилось из-за того, что мы не можем провести оценку более чем в 2 раза отличающуюся от текущего размера). &amp;lt;math&amp;gt;N_0&amp;lt;/math&amp;gt; - это число входных точек, загруженных в память с пороговым ограничением &amp;lt;math&amp;gt;T_0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Соответственно, итоговая сложность фазы 1 &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P})+log_2\frac{N}{N_0}*d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Анализ фазы 2 проводится аналогично.&lt;br /&gt;
&lt;br /&gt;
Что касается операций ввода-вывода, то в фазе 1 данные сканируются один раз, а в фазе 2 не сканируются вовсе.&lt;br /&gt;
Некоторое количество вычислений связано с удалением точек из областей с низкой плотностью.&lt;br /&gt;
Если количество доступной для этой операции памяти не больше &#039;&#039;M&#039;&#039; и проведено порядка &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; перестроек дерева, то сложность ввода-вывода для фазы 1 существенно не отличается от сложности чтения из файла. Основываясь рассуждениях выше, сложность фаз 1 и 2 будет линейно увеличиваться с ростом N.&lt;br /&gt;
&lt;br /&gt;
В фазе 3 нет операций ввода-вывода. Её сложность ограничена константой, которая зависит от максимального размера входных данных, и варианта выбранного алгоритма для кластеризации. &lt;br /&gt;
&lt;br /&gt;
Фаза 4 снова сканирует данные и записывает каждую точку в подходящий кластер; время работы пропорционально &amp;lt;math&amp;gt;N*K&amp;lt;/math&amp;gt;.   &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Достоинства алгоритма ===&lt;br /&gt;
По сравнению с предыдущими методами BIRCH обладает следующими достоинствами:&lt;br /&gt;
&lt;br /&gt;
1. BIRCH является локальным алгоритмом, то есть каждое решение о каждом элементе кластера принимается без повторного сканирования данных или уже существующих кластеров. Используются только метрики, отражающие близость элементов друг к другу.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH использует факт неравномерного распределения данных в пространстве и поэтому не все данные рассматриваются как одинаково важные для построения кластера. Области с большой плотностью обрабатываются как единый кластер. Данные в более разреженных областях могут удаляться (опционально).&lt;br /&gt;
&lt;br /&gt;
3. BIRCH использует всю доступную память для получения наилучших из возможных подкластеров, в то же время минимизируя затраты на операции ввода/вывода. Оптимизация процесса кластеризации достигается за счет использования взвешенно-сбалансированного дерева. При этом время исполнения линейно.&lt;br /&gt;
&lt;br /&gt;
4. BIRCH не требует всего набора данных заранее (при этом просматривает его всего один раз).&lt;br /&gt;
&lt;br /&gt;
=== Недостатки алгоритма ===&lt;br /&gt;
&lt;br /&gt;
1. Алгоритм позволяет работать только с числовыми данными.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH хорошо выделяет только кластеры сферической формы.&lt;br /&gt;
&lt;br /&gt;
3. Существует необходимость в задании пороговых значений.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&lt;br /&gt;
[1] Википедия&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;/div&gt;</summary>
		<author><name>Светлана Морозова</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13498</id>
		<title>Участник:Smirnov.maxim/BIRCH</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13498"/>
		<updated>2016-10-23T09:37:04Z</updated>

		<summary type="html">&lt;p&gt;Светлана Морозова: /* Недостатки алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Нахождение полезных для анализа закономерностей в больших объёмах данных с недавних пор вызывает значительный интерес. В связи с этим ввелось и стало активно развиваться такое понятие как &#039;&#039;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7 кластеризация]&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Ранние работы и алгоритмы, разработанные в этой области, не уделяли достаточного внимания анализу очень больших наборов данных или минимизации издержек на процессы ввода-вывода.&lt;br /&gt;
Решением этих проблем стал алгоритм, известный как BIRCH.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIRCH&#039;&#039;&#039; (balanced iterative reducing and clustering using hierarchies)- алгоритм, применяемый в области [https://ru.wikipedia.org/wiki/Data_mining Data mining] и использующий принципы [https://ru.wikipedia.org/wiki/%D0%98%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F иерархической кластеризации].&lt;br /&gt;
&lt;br /&gt;
Если имеется очень большой набор данных, то в пространстве он распределен, как правило, неравномерно. Кластерный анализ определяет места наибольшего и наименьшего скоплений, чтобы таким образом понять всю картину целиком. Кроме того, полученные кластеры визуализируются гораздо нагляднее, чем начальные &amp;quot;сырые&amp;quot; данные.&lt;br /&gt;
Задачей алгоритмов кластеризации является не только простое разбиение данных на кластеры, но и работа в рамках ограниченного объёма доступной памяти (как правило, её объём гораздо меньше, чем размер исходного набора данных) и минимизация времени, требуемого на операции ввода-вывода.&lt;br /&gt;
&lt;br /&gt;
Для наилучшего решения этих проблем BIRCH распределяет входящие данные по кластерам динамически. Для эффективной кластеризации алгоритму требуется всего одно сканирование данных (т.е. с увеличением количества данных сложность увеличивается линейно). А при помощи одной (или более) дополнительных итераций можно и далее улучшать эффективность. BIRCH также является первым алгоритмом, предложенным для эффективного управления &amp;quot;шумами&amp;quot; (данными, которые не вписываются в общее представление модели).&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Теоретическая основа ===&lt;br /&gt;
&lt;br /&gt;
Пусть в кластере имеются &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}, i=1,2,...,N&amp;lt;/math&amp;gt;.&lt;br /&gt;
Тогда &#039;&#039;&#039;центроид&#039;&#039;&#039; &amp;lt;math&amp;gt;{\vec{{X_0}}}&amp;lt;/math&amp;gt;, &#039;&#039;&#039;радиус&#039;&#039;&#039; &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &#039;&#039;&#039;диаметр&#039;&#039;&#039; &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластера определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;{\vec{X_0}}=\frac{\sum_{i=1}^N\vec{X_i}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{\sum_{i=1}^N{(\vec{X_i} - \vec{X_0})}^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{\sum_{i=1}^N\sum_{j=1}^N{(\vec{X_i} - \vec{X_j})}^2}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; - это среднее расстояние от каждой точки до центроида. &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; - это среднее расстояние между парами в кластере. Данные величины являются альтернативными метриками плотности кластера относительно центроида.&lt;br /&gt;
&lt;br /&gt;
Для измерения близости друг к другу двух кластеров вводятся следующие метрики:&lt;br /&gt;
&lt;br /&gt;
пусть даны центроиды двух кластеров &amp;lt;math&amp;gt;\vec{X_{01}}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\vec{X_{02}}&amp;lt;/math&amp;gt;.&lt;br /&gt;
Евклидова метрика &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt; и метрика Манхэттена &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt; между двумя кластерами определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_0 = ((\vec{X_{01}}-\vec{X_{02}})^2)^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_1 = |\vec{X_{01}}-\vec{X_{02}}| = \sum_{i=1}^d |{\vec{X_{01}}}^{(i)}-{\vec{X_{02}}}^{(i)}| &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть имеются два кластера, содержащих соответственно  &amp;lt;math&amp;gt;N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;N_2&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i= 1,2, ...,N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\{\vec{X_j}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j= N_1+1,N_1+2, ...,N_1+N_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Среднее расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &#039;&#039;&#039;среднее внутрикластерное расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &#039;&#039;&#039;дисперсия&#039;&#039;&#039; &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; для двух кластеров определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{\sum_{i=1}^{N_1}\sum_{j=N_1+1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{N_1N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{\sum_{i=1}^{N_1+N_2}\sum_{j=1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_4 = \sum_{k=1}^{N_1+N_2}(\vec{X_k} - \frac{\sum_{i=1}^{N_1+N_2}\vec{X_i}}{N_1+N_2})^2 - \sum_{i=1}^{N_1}(\vec{X_i} - \frac{\sum_{i=1}^{N_1}\vec{X_i}}{N_1})^2 - \sum_{j=N_1+1}^{N_1+N_2}(\vec{X_j} - \frac{\sum_{i=N_1+1}^{N_1+N_2}\vec{X_i}}{N_2})^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Таким образом, величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; относятся к отдельным кластерам, а &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; - к объединению двух кластеров.&lt;br /&gt;
&lt;br /&gt;
=== Кластерный элемент и кластерное дерево ===&lt;br /&gt;
&lt;br /&gt;
В основе концепции алгоритма BIRCH лежат понятия &#039;&#039;&#039;кластерного элемента&#039;&#039;&#039; и &#039;&#039;&#039;кластерного дерева (CF Tree)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====Кластерный элемент ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; Пусть в кластере содержатся  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности  &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;:&amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;i=1,2,...,N&amp;lt;/math&amp;gt;. &lt;br /&gt;
&#039;&#039;&#039;Кластерный элемент (CF)&#039;&#039;&#039; - тройка чисел, характеризующая информацию о кластере: &lt;br /&gt;
&amp;lt;math&amp;gt;CF = (N, \vec{LS}, SS)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - количество элементов входных данных, содержащихся в кластере, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; - линейная сумма входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}\vec{X_i}&amp;lt;/math&amp;gt;), &amp;lt;math&amp;gt;SS&amp;lt;/math&amp;gt; - сумма квадратов входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}{\vec{X_i}}^2&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Теорема&#039;&#039;&#039; Пусть &amp;lt;math&amp;gt;CF_1 = (N_1, \vec{LS_1}, SS_1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;CF_2 = (N_1, \vec{LS_2}, SS_2)&amp;lt;/math&amp;gt; - CF векторы двух непересекающихся кластеров. Тогда при их объединении образуется кластер со следующим CF вектором: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF = CF_1 + CF_2 = (N_1+N_2, \vec{LS_1}+\vec{LS_2}, SS_1+SS_2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Из указанных выше определения и теоремы вытекает тот факт, что при объединении кластеров их CF вектор может вычисляться инкрементно и точно. &lt;br /&gt;
Легко показать, что вычислить величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;, как и обычные метрики, также не составит труда.&lt;br /&gt;
&lt;br /&gt;
Таким образом, в данном случае информацией о кластере является не весь набор точек, а вектор CF. Хранение одного только вектора может показаться неэффективным, но этого вполне достаточно для оперирования всеми необходимыми метриками, на основе которых принимаются решения в алгоритме BIRCH.&lt;br /&gt;
&lt;br /&gt;
==== Кластерное дерево ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; &#039;&#039;&#039;Кластерное дерево (CF Tree)&#039;&#039;&#039; - это взвешенно сбалансированное дерево с двумя параметрами: &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - коэффициент разветвления, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - пороговая величина. Каждый нелистьевой узел дерева имеет не более чем &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; вхождений узлов следующей формы: &amp;lt;math&amp;gt;[CF_i,child_i]&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i=1,2,...,B&amp;lt;/math&amp;gt;, &#039;&#039;child&#039;&#039; - указатель на i-й дочерний узел, &amp;lt;math&amp;gt;CF_i&amp;lt;/math&amp;gt; - CF вектор соответствующего подкластера.&lt;br /&gt;
&lt;br /&gt;
Каждый листьевой узел имеет ссылку на два соседних узла (&#039;&#039;prev&#039;&#039; и &#039;&#039;next&#039;&#039;) для того, чтобы связать все узлы для эффективного сканирования.&lt;br /&gt;
Все листьевые узлы должны удовлетворять пороговому ограничению &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, т.е. диаметр (радиус) не должен превосходить &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;.&lt;br /&gt;
В процессе вставки новых данных CF дерево строится динамически. Оно использует вставку данных для кластеризации точно также как &amp;lt;math&amp;gt;B+&amp;lt;/math&amp;gt; [https://ru.wikipedia.org/wiki/B%2B-%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE дерево] использует её для поиска.&lt;br /&gt;
CF дерево очень компактно, поскольку каждый листьевой узел - это не просто точка, а подкластер (который объединяет множество точек с учётом ограничения &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Операция вставки в &#039;&#039;&#039;CF&#039;&#039;&#039; дерево ====&lt;br /&gt;
&lt;br /&gt;
Опишем алгоритм вставки элемнта &amp;lt;math&amp;gt;Ent&amp;lt;/math&amp;gt; в CF дерево:&lt;br /&gt;
&lt;br /&gt;
1) &#039;&#039;Определение подходящего листа&#039;&#039;: Начиная с корня, алгоритм рекурсивно спускается по CF дереву, выбирая &#039;&#039;&#039;ближайший&#039;&#039;&#039; дочерний узел в соответствии с выбранной метрикой &amp;lt;math&amp;gt;D0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D4&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &#039;&#039;Преобразование листа&#039;&#039;: Когда алгоритм доходит до листа, он находит ближайшую листьевой элемент, скажем, &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;, а затем проверяет, можно ли добавить &#039;&#039;Ent&#039;&#039; к &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt; без нарушения порогового условия. Если да, то с учётом этого изменяется CF вектор для &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;; если нет, то &#039;&#039;Ent&#039;&#039; становится новым элементом листа. Если в листе для этого достаточно места, то шаг окончен, иначе он должен &amp;quot;расщепиться&amp;quot;. Расщепление узла производится при помощи выбора за основу наиболее удалённой друг от друга пары элементов и перераспределение оставшихся элементов в соответствии с выбранным критерием близости.&lt;br /&gt;
&lt;br /&gt;
3) &#039;&#039;Преобразование пути к листу&#039;&#039;: После вставки &#039;&#039;Ent&#039;&#039; в лист мы должны обновить информацию о CF для каждого нелистьевого элемента на пути к листу. При отсутствии расщепления это означает простое сложение CF векторов для отражения факта добавления &#039;&#039;Ent&#039;&#039;. Расщепление листа же требует вставки нового нелистьевого элемента в родительский узел для задания только что созданного листа. Если у родителя есть место для этого элемента, то необходимо просто преобразовать CF векторы на всех более высоких уровнях. В общем случае, однако, нам также придётся расщепить родительский узел, и так далее до корня. Если расщеплён корень, то высота дерева увеличивается на единицу.&lt;br /&gt;
&lt;br /&gt;
4) &#039;&#039;Улучшение слияния&#039;&#039;: Расщепление вызвано ограничением на размер узла, который не зависит от кластеризационных свойств данных. Если во входящем потоке присутствуют &amp;quot;искажённые&amp;quot; (из областей с низкой плотностью) данные, это может повлиять на качество кластеризации, а также уменьшить эффективность использования памяти. Дополнительный шаг алгоритма помогает решить эти проблемы: предположим, что произошло расщепление листа, и распространение этого процесса остановилось на некотором нелистьевом узле &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt;, то есть &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; может вместить дополнительный элемент, полученный после расщепления. Теперь мы сканируем узел &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; для нахождения двух наиболее близких элементов. Если это не пара, отвечающая расщеплению, мы пытаемся объединить их и поставить в соответствие два дочерних узла. Если количество элементов в дочерних узлах  больше B, мы снова расщепляем результат объединения.&lt;br /&gt;
В процессе повторного расщепления, в случае, если один источник собирает достаточно элементов для того, чтобы полностью заполнить узел, оставшиеся элементы передаются другом источнику. В итоге, если объединённые элементы помещаются в одном узле, в нём освобождается место для ещё одного элемента. Тем самым увеличивается степень использования свободного пространства и откладывается дальнейшее расщепление. В ином случае мы улучшаем распределение элементов в двух ближайших подкластерах.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро алгоритма заключается в многократном выполнении операции вставки нового элемента в дерево, в процессе чего требуется вычисление следующих величин:&lt;br /&gt;
&lt;br /&gt;
* радиуса &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; или диаметра &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластерного элемента. Выполняется при попытке вставить новый элемент в один из подкластеров листьевого узла дерева.&lt;br /&gt;
&lt;br /&gt;
* расстояния между двумя элементами. Выполняется при поиске ближайшего по отношению к новому элементу подкластера в узле дерева по одной из рассмотренных в разд. 1.2.1 метрик &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Зная характеристики кластерных элементов &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;, в результате алгебраических преобразований можно получить следующие упрощенные формулы вычисления необходимых значений:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\vec{X_0} = \frac{\vec{LS}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{SS - 2\vec{X_0}\vec{LS} + N(\vec{X_0})^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{2(N*SS - (\vec{LS})^2)}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{N_1*SS_2 + N_2*SS_1 - 2\vec{LS_1}\vec{LS_2}}{N_1*N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{2((N_1+N_2)(SS_1+SS_2)-(\vec{LS_1}+\vec{LS_2})^2)}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Реализация алгоритма BIRCH состояит из следующих четырёх фаз:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 1&#039;&#039;&#039;. Главной задачей фазы 1 является сканирование всех данных и построение в памяти исходного CF дерева, используя заданное количество памяти. Это дерево стремится отразить информацию о кластеризации данных настолько хорошо, насколько это позволяют ограничения по памяти. При этом плотно распределённые данные группируются в подкластеры, а более разрозненные данные удаляются. После завершения фазы 1 вспомогательные вычисления в дальнейших фазах будут:&lt;br /&gt;
&lt;br /&gt;
1) быстрее, потому что (а) больше не нужны операции ввода-вывода, (b) проблема кластеризации начальных данных упрощается до проблемы кластеризации подкластеров в листьях;&lt;br /&gt;
&lt;br /&gt;
2) точнее, потому что (а) большинство данных с низкой плотностью удалены, (b) оставшиеся данные распределены оптимально (в соответствии с доступным количеством памяти);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 2&#039;&#039;&#039;. Данная фаза является опциональной. Известно, что существующие методы глобальной кластеризации, используемые в рамках фазы 3, имеют различные диапазоны входных значений, при которых их реализация наиболее эффективна. Поэтому потенциально существует пробел между размером фазы 1 и входными значениями фазы 3. И фаза 2 как раз является недостающим связующим звеном: так же как и фаза 1, она сканирует листьевые элементы начального CF дерева для того, чтобы построить меньшее дерево, удаляя ещё больше элементов с низкой плотностью и группируя переполненные подкластеры в большие кластеры.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 3&#039;&#039;&#039;. В данной фазе для листьевых элементов применяется (любой подходящий) алгоритм глобальной кластеризации. Существующие алгоритмы кластеризации наборов точек могут также работать с наборами подкластеров, каждый из которых представлен своим CF вектором. Зная CF вектор, можно вычислить центроид и в дальнейшем заменить всю информацию о кластере этим значением (этого достаточно для вычисления большинства необходимых метрик). После фазы 3 мы получаем набор кластеров, который отражает основные характеристики распределяемых данных.&lt;br /&gt;
Однако, всё ещё могут оставаться некоторые неточности, для устранения которых существует фаза 4.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 4&#039;&#039;&#039;. Данная фаза является опциональной и влечёт за собой затраты на дополнительное сканирование данных для корректировки неточностей и дальнейшего улучшения кластеризации. Фаза 4 использует центроиды кластеров, полученные в фазе 3 для как основы и перераспределяет точки входных данных в ближайшие для них основы для получения нового списка кластеров. Фаза 4, если это необходимо пользователю, может быть расширена дополнительными проходами для уверенности в том, что результат приближается к оптимальному.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Для начала проанализируем вычислительную сложность фазы 1.&lt;br /&gt;
Максимальный размер дерева &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt;. Для того чтобы вставить элемент, мы должны пройти путь от корня до листа (это около &amp;lt;math&amp;gt;1+log_B\frac{M}{P}&amp;lt;/math&amp;gt; узлов). В каждом узле в поисках &amp;quot;ближайшего&amp;quot; нам необходимо просмотреть B элементов; сложность для каждого элемента пропорциональна размерности &#039;&#039;d&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Поэтому сложность вставки всех входных точек &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В случае, когда необходимо перестроить дерево, предположим, что ES - это размер CF элемента. Существует максимум &amp;lt;math&amp;gt;\frac{M}{ES}&amp;lt;/math&amp;gt; листьевых элементов для вставки, поэтому сложность повторной вставки листьевых элементов &amp;lt;math&amp;gt;O(d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Количество итераций перестройки дерева зависит от пороговой величины. На самом деле, это около &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; (двоичное основание появилось из-за того, что мы не можем провести оценку более чем в 2 раза отличающуюся от текущего размера). &amp;lt;math&amp;gt;N_0&amp;lt;/math&amp;gt; - это число входных точек, загруженных в память с пороговым ограничением &amp;lt;math&amp;gt;T_0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Соответственно, итоговая сложность фазы 1 &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P})+log_2\frac{N}{N_0}*d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Анализ фазы 2 проводится аналогично.&lt;br /&gt;
&lt;br /&gt;
Что касается операций ввода-вывода, то в фазе 1 данные сканируются один раз, а в фазе 2 не сканируются вовсе.&lt;br /&gt;
Некоторое количество вычислений связано с удалением точек из областей с низкой плотностью.&lt;br /&gt;
Если количество доступной для этой операции памяти не больше &#039;&#039;M&#039;&#039; и проведено порядка &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; перестроек дерева, то сложность ввода-вывода для фазы 1 существенно не отличается от сложности чтения из файла. Основываясь рассуждениях выше, сложность фаз 1 и 2 будет линейно увеличиваться с ростом N.&lt;br /&gt;
&lt;br /&gt;
В фазе 3 нет операций ввода-вывода. Её сложность ограничена константой, которая зависит от максимального размера входных данных, и варианта выбранного алгоритма для кластеризации. &lt;br /&gt;
&lt;br /&gt;
Фаза 4 снова сканирует данные и записывает каждую точку в подходящий кластер; время работы пропорционально &amp;lt;math&amp;gt;N*K&amp;lt;/math&amp;gt;.   &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Достоинства алгоритма ===&lt;br /&gt;
По сравнению с предыдущими методами BIRCH обладает следующими достоинствами:&lt;br /&gt;
&lt;br /&gt;
1. BIRCH является локальным алгоритмом, то есть каждое решение о каждом элементе кластера принимается без повторного сканирования данных или уже существующих кластеров. Используются только метрики, отражающие близость элементов друг к другу.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH использует факт неравномерного распределения данных в пространстве и поэтому не все данные рассматриваются как одинаково важные для построения кластера. Области с большой плотностью обрабатываются как единый кластер. Данные в более разреженных областях могут удаляться (опционально).&lt;br /&gt;
&lt;br /&gt;
3. BIRCH использует всю доступную память для получения наилучших из возможных подкластеров, в то же время минимизируя затраты на операции ввода/вывода. Оптимизация процесса кластеризации достигается за счет использования взвешенно-сбалансированного дерева. При этом время исполнения линейно.&lt;br /&gt;
&lt;br /&gt;
4. BIRCH не требует всего набора данных заранее (при этом просматривает его всего один раз).&lt;br /&gt;
&lt;br /&gt;
=== Недостатки алгоритма ===&lt;br /&gt;
&lt;br /&gt;
1. Работа только с числовыми данными.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH хорошо выделяет только кластеры сферической формы.&lt;br /&gt;
&lt;br /&gt;
3. Существует необходимость в задании пороговых значений.&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&lt;br /&gt;
[1] Википедия&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;/div&gt;</summary>
		<author><name>Светлана Морозова</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13497</id>
		<title>Участник:Smirnov.maxim/BIRCH</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13497"/>
		<updated>2016-10-23T09:36:49Z</updated>

		<summary type="html">&lt;p&gt;Светлана Морозова: /* Свойства алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Нахождение полезных для анализа закономерностей в больших объёмах данных с недавних пор вызывает значительный интерес. В связи с этим ввелось и стало активно развиваться такое понятие как &#039;&#039;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7 кластеризация]&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Ранние работы и алгоритмы, разработанные в этой области, не уделяли достаточного внимания анализу очень больших наборов данных или минимизации издержек на процессы ввода-вывода.&lt;br /&gt;
Решением этих проблем стал алгоритм, известный как BIRCH.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIRCH&#039;&#039;&#039; (balanced iterative reducing and clustering using hierarchies)- алгоритм, применяемый в области [https://ru.wikipedia.org/wiki/Data_mining Data mining] и использующий принципы [https://ru.wikipedia.org/wiki/%D0%98%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F иерархической кластеризации].&lt;br /&gt;
&lt;br /&gt;
Если имеется очень большой набор данных, то в пространстве он распределен, как правило, неравномерно. Кластерный анализ определяет места наибольшего и наименьшего скоплений, чтобы таким образом понять всю картину целиком. Кроме того, полученные кластеры визуализируются гораздо нагляднее, чем начальные &amp;quot;сырые&amp;quot; данные.&lt;br /&gt;
Задачей алгоритмов кластеризации является не только простое разбиение данных на кластеры, но и работа в рамках ограниченного объёма доступной памяти (как правило, её объём гораздо меньше, чем размер исходного набора данных) и минимизация времени, требуемого на операции ввода-вывода.&lt;br /&gt;
&lt;br /&gt;
Для наилучшего решения этих проблем BIRCH распределяет входящие данные по кластерам динамически. Для эффективной кластеризации алгоритму требуется всего одно сканирование данных (т.е. с увеличением количества данных сложность увеличивается линейно). А при помощи одной (или более) дополнительных итераций можно и далее улучшать эффективность. BIRCH также является первым алгоритмом, предложенным для эффективного управления &amp;quot;шумами&amp;quot; (данными, которые не вписываются в общее представление модели).&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Теоретическая основа ===&lt;br /&gt;
&lt;br /&gt;
Пусть в кластере имеются &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}, i=1,2,...,N&amp;lt;/math&amp;gt;.&lt;br /&gt;
Тогда &#039;&#039;&#039;центроид&#039;&#039;&#039; &amp;lt;math&amp;gt;{\vec{{X_0}}}&amp;lt;/math&amp;gt;, &#039;&#039;&#039;радиус&#039;&#039;&#039; &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &#039;&#039;&#039;диаметр&#039;&#039;&#039; &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластера определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;{\vec{X_0}}=\frac{\sum_{i=1}^N\vec{X_i}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{\sum_{i=1}^N{(\vec{X_i} - \vec{X_0})}^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{\sum_{i=1}^N\sum_{j=1}^N{(\vec{X_i} - \vec{X_j})}^2}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; - это среднее расстояние от каждой точки до центроида. &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; - это среднее расстояние между парами в кластере. Данные величины являются альтернативными метриками плотности кластера относительно центроида.&lt;br /&gt;
&lt;br /&gt;
Для измерения близости друг к другу двух кластеров вводятся следующие метрики:&lt;br /&gt;
&lt;br /&gt;
пусть даны центроиды двух кластеров &amp;lt;math&amp;gt;\vec{X_{01}}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\vec{X_{02}}&amp;lt;/math&amp;gt;.&lt;br /&gt;
Евклидова метрика &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt; и метрика Манхэттена &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt; между двумя кластерами определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_0 = ((\vec{X_{01}}-\vec{X_{02}})^2)^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_1 = |\vec{X_{01}}-\vec{X_{02}}| = \sum_{i=1}^d |{\vec{X_{01}}}^{(i)}-{\vec{X_{02}}}^{(i)}| &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть имеются два кластера, содержащих соответственно  &amp;lt;math&amp;gt;N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;N_2&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i= 1,2, ...,N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\{\vec{X_j}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j= N_1+1,N_1+2, ...,N_1+N_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Среднее расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &#039;&#039;&#039;среднее внутрикластерное расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &#039;&#039;&#039;дисперсия&#039;&#039;&#039; &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; для двух кластеров определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{\sum_{i=1}^{N_1}\sum_{j=N_1+1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{N_1N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{\sum_{i=1}^{N_1+N_2}\sum_{j=1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_4 = \sum_{k=1}^{N_1+N_2}(\vec{X_k} - \frac{\sum_{i=1}^{N_1+N_2}\vec{X_i}}{N_1+N_2})^2 - \sum_{i=1}^{N_1}(\vec{X_i} - \frac{\sum_{i=1}^{N_1}\vec{X_i}}{N_1})^2 - \sum_{j=N_1+1}^{N_1+N_2}(\vec{X_j} - \frac{\sum_{i=N_1+1}^{N_1+N_2}\vec{X_i}}{N_2})^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Таким образом, величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; относятся к отдельным кластерам, а &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; - к объединению двух кластеров.&lt;br /&gt;
&lt;br /&gt;
=== Кластерный элемент и кластерное дерево ===&lt;br /&gt;
&lt;br /&gt;
В основе концепции алгоритма BIRCH лежат понятия &#039;&#039;&#039;кластерного элемента&#039;&#039;&#039; и &#039;&#039;&#039;кластерного дерева (CF Tree)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====Кластерный элемент ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; Пусть в кластере содержатся  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности  &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;:&amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;i=1,2,...,N&amp;lt;/math&amp;gt;. &lt;br /&gt;
&#039;&#039;&#039;Кластерный элемент (CF)&#039;&#039;&#039; - тройка чисел, характеризующая информацию о кластере: &lt;br /&gt;
&amp;lt;math&amp;gt;CF = (N, \vec{LS}, SS)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - количество элементов входных данных, содержащихся в кластере, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; - линейная сумма входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}\vec{X_i}&amp;lt;/math&amp;gt;), &amp;lt;math&amp;gt;SS&amp;lt;/math&amp;gt; - сумма квадратов входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}{\vec{X_i}}^2&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Теорема&#039;&#039;&#039; Пусть &amp;lt;math&amp;gt;CF_1 = (N_1, \vec{LS_1}, SS_1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;CF_2 = (N_1, \vec{LS_2}, SS_2)&amp;lt;/math&amp;gt; - CF векторы двух непересекающихся кластеров. Тогда при их объединении образуется кластер со следующим CF вектором: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF = CF_1 + CF_2 = (N_1+N_2, \vec{LS_1}+\vec{LS_2}, SS_1+SS_2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Из указанных выше определения и теоремы вытекает тот факт, что при объединении кластеров их CF вектор может вычисляться инкрементно и точно. &lt;br /&gt;
Легко показать, что вычислить величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;, как и обычные метрики, также не составит труда.&lt;br /&gt;
&lt;br /&gt;
Таким образом, в данном случае информацией о кластере является не весь набор точек, а вектор CF. Хранение одного только вектора может показаться неэффективным, но этого вполне достаточно для оперирования всеми необходимыми метриками, на основе которых принимаются решения в алгоритме BIRCH.&lt;br /&gt;
&lt;br /&gt;
==== Кластерное дерево ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; &#039;&#039;&#039;Кластерное дерево (CF Tree)&#039;&#039;&#039; - это взвешенно сбалансированное дерево с двумя параметрами: &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - коэффициент разветвления, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - пороговая величина. Каждый нелистьевой узел дерева имеет не более чем &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; вхождений узлов следующей формы: &amp;lt;math&amp;gt;[CF_i,child_i]&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i=1,2,...,B&amp;lt;/math&amp;gt;, &#039;&#039;child&#039;&#039; - указатель на i-й дочерний узел, &amp;lt;math&amp;gt;CF_i&amp;lt;/math&amp;gt; - CF вектор соответствующего подкластера.&lt;br /&gt;
&lt;br /&gt;
Каждый листьевой узел имеет ссылку на два соседних узла (&#039;&#039;prev&#039;&#039; и &#039;&#039;next&#039;&#039;) для того, чтобы связать все узлы для эффективного сканирования.&lt;br /&gt;
Все листьевые узлы должны удовлетворять пороговому ограничению &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, т.е. диаметр (радиус) не должен превосходить &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;.&lt;br /&gt;
В процессе вставки новых данных CF дерево строится динамически. Оно использует вставку данных для кластеризации точно также как &amp;lt;math&amp;gt;B+&amp;lt;/math&amp;gt; [https://ru.wikipedia.org/wiki/B%2B-%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE дерево] использует её для поиска.&lt;br /&gt;
CF дерево очень компактно, поскольку каждый листьевой узел - это не просто точка, а подкластер (который объединяет множество точек с учётом ограничения &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Операция вставки в &#039;&#039;&#039;CF&#039;&#039;&#039; дерево ====&lt;br /&gt;
&lt;br /&gt;
Опишем алгоритм вставки элемнта &amp;lt;math&amp;gt;Ent&amp;lt;/math&amp;gt; в CF дерево:&lt;br /&gt;
&lt;br /&gt;
1) &#039;&#039;Определение подходящего листа&#039;&#039;: Начиная с корня, алгоритм рекурсивно спускается по CF дереву, выбирая &#039;&#039;&#039;ближайший&#039;&#039;&#039; дочерний узел в соответствии с выбранной метрикой &amp;lt;math&amp;gt;D0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D4&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &#039;&#039;Преобразование листа&#039;&#039;: Когда алгоритм доходит до листа, он находит ближайшую листьевой элемент, скажем, &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;, а затем проверяет, можно ли добавить &#039;&#039;Ent&#039;&#039; к &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt; без нарушения порогового условия. Если да, то с учётом этого изменяется CF вектор для &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;; если нет, то &#039;&#039;Ent&#039;&#039; становится новым элементом листа. Если в листе для этого достаточно места, то шаг окончен, иначе он должен &amp;quot;расщепиться&amp;quot;. Расщепление узла производится при помощи выбора за основу наиболее удалённой друг от друга пары элементов и перераспределение оставшихся элементов в соответствии с выбранным критерием близости.&lt;br /&gt;
&lt;br /&gt;
3) &#039;&#039;Преобразование пути к листу&#039;&#039;: После вставки &#039;&#039;Ent&#039;&#039; в лист мы должны обновить информацию о CF для каждого нелистьевого элемента на пути к листу. При отсутствии расщепления это означает простое сложение CF векторов для отражения факта добавления &#039;&#039;Ent&#039;&#039;. Расщепление листа же требует вставки нового нелистьевого элемента в родительский узел для задания только что созданного листа. Если у родителя есть место для этого элемента, то необходимо просто преобразовать CF векторы на всех более высоких уровнях. В общем случае, однако, нам также придётся расщепить родительский узел, и так далее до корня. Если расщеплён корень, то высота дерева увеличивается на единицу.&lt;br /&gt;
&lt;br /&gt;
4) &#039;&#039;Улучшение слияния&#039;&#039;: Расщепление вызвано ограничением на размер узла, который не зависит от кластеризационных свойств данных. Если во входящем потоке присутствуют &amp;quot;искажённые&amp;quot; (из областей с низкой плотностью) данные, это может повлиять на качество кластеризации, а также уменьшить эффективность использования памяти. Дополнительный шаг алгоритма помогает решить эти проблемы: предположим, что произошло расщепление листа, и распространение этого процесса остановилось на некотором нелистьевом узле &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt;, то есть &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; может вместить дополнительный элемент, полученный после расщепления. Теперь мы сканируем узел &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; для нахождения двух наиболее близких элементов. Если это не пара, отвечающая расщеплению, мы пытаемся объединить их и поставить в соответствие два дочерних узла. Если количество элементов в дочерних узлах  больше B, мы снова расщепляем результат объединения.&lt;br /&gt;
В процессе повторного расщепления, в случае, если один источник собирает достаточно элементов для того, чтобы полностью заполнить узел, оставшиеся элементы передаются другом источнику. В итоге, если объединённые элементы помещаются в одном узле, в нём освобождается место для ещё одного элемента. Тем самым увеличивается степень использования свободного пространства и откладывается дальнейшее расщепление. В ином случае мы улучшаем распределение элементов в двух ближайших подкластерах.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро алгоритма заключается в многократном выполнении операции вставки нового элемента в дерево, в процессе чего требуется вычисление следующих величин:&lt;br /&gt;
&lt;br /&gt;
* радиуса &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; или диаметра &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластерного элемента. Выполняется при попытке вставить новый элемент в один из подкластеров листьевого узла дерева.&lt;br /&gt;
&lt;br /&gt;
* расстояния между двумя элементами. Выполняется при поиске ближайшего по отношению к новому элементу подкластера в узле дерева по одной из рассмотренных в разд. 1.2.1 метрик &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Зная характеристики кластерных элементов &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;, в результате алгебраических преобразований можно получить следующие упрощенные формулы вычисления необходимых значений:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\vec{X_0} = \frac{\vec{LS}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{SS - 2\vec{X_0}\vec{LS} + N(\vec{X_0})^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{2(N*SS - (\vec{LS})^2)}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{N_1*SS_2 + N_2*SS_1 - 2\vec{LS_1}\vec{LS_2}}{N_1*N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{2((N_1+N_2)(SS_1+SS_2)-(\vec{LS_1}+\vec{LS_2})^2)}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Реализация алгоритма BIRCH состояит из следующих четырёх фаз:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 1&#039;&#039;&#039;. Главной задачей фазы 1 является сканирование всех данных и построение в памяти исходного CF дерева, используя заданное количество памяти. Это дерево стремится отразить информацию о кластеризации данных настолько хорошо, насколько это позволяют ограничения по памяти. При этом плотно распределённые данные группируются в подкластеры, а более разрозненные данные удаляются. После завершения фазы 1 вспомогательные вычисления в дальнейших фазах будут:&lt;br /&gt;
&lt;br /&gt;
1) быстрее, потому что (а) больше не нужны операции ввода-вывода, (b) проблема кластеризации начальных данных упрощается до проблемы кластеризации подкластеров в листьях;&lt;br /&gt;
&lt;br /&gt;
2) точнее, потому что (а) большинство данных с низкой плотностью удалены, (b) оставшиеся данные распределены оптимально (в соответствии с доступным количеством памяти);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 2&#039;&#039;&#039;. Данная фаза является опциональной. Известно, что существующие методы глобальной кластеризации, используемые в рамках фазы 3, имеют различные диапазоны входных значений, при которых их реализация наиболее эффективна. Поэтому потенциально существует пробел между размером фазы 1 и входными значениями фазы 3. И фаза 2 как раз является недостающим связующим звеном: так же как и фаза 1, она сканирует листьевые элементы начального CF дерева для того, чтобы построить меньшее дерево, удаляя ещё больше элементов с низкой плотностью и группируя переполненные подкластеры в большие кластеры.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 3&#039;&#039;&#039;. В данной фазе для листьевых элементов применяется (любой подходящий) алгоритм глобальной кластеризации. Существующие алгоритмы кластеризации наборов точек могут также работать с наборами подкластеров, каждый из которых представлен своим CF вектором. Зная CF вектор, можно вычислить центроид и в дальнейшем заменить всю информацию о кластере этим значением (этого достаточно для вычисления большинства необходимых метрик). После фазы 3 мы получаем набор кластеров, который отражает основные характеристики распределяемых данных.&lt;br /&gt;
Однако, всё ещё могут оставаться некоторые неточности, для устранения которых существует фаза 4.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 4&#039;&#039;&#039;. Данная фаза является опциональной и влечёт за собой затраты на дополнительное сканирование данных для корректировки неточностей и дальнейшего улучшения кластеризации. Фаза 4 использует центроиды кластеров, полученные в фазе 3 для как основы и перераспределяет точки входных данных в ближайшие для них основы для получения нового списка кластеров. Фаза 4, если это необходимо пользователю, может быть расширена дополнительными проходами для уверенности в том, что результат приближается к оптимальному.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Для начала проанализируем вычислительную сложность фазы 1.&lt;br /&gt;
Максимальный размер дерева &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt;. Для того чтобы вставить элемент, мы должны пройти путь от корня до листа (это около &amp;lt;math&amp;gt;1+log_B\frac{M}{P}&amp;lt;/math&amp;gt; узлов). В каждом узле в поисках &amp;quot;ближайшего&amp;quot; нам необходимо просмотреть B элементов; сложность для каждого элемента пропорциональна размерности &#039;&#039;d&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Поэтому сложность вставки всех входных точек &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В случае, когда необходимо перестроить дерево, предположим, что ES - это размер CF элемента. Существует максимум &amp;lt;math&amp;gt;\frac{M}{ES}&amp;lt;/math&amp;gt; листьевых элементов для вставки, поэтому сложность повторной вставки листьевых элементов &amp;lt;math&amp;gt;O(d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Количество итераций перестройки дерева зависит от пороговой величины. На самом деле, это около &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; (двоичное основание появилось из-за того, что мы не можем провести оценку более чем в 2 раза отличающуюся от текущего размера). &amp;lt;math&amp;gt;N_0&amp;lt;/math&amp;gt; - это число входных точек, загруженных в память с пороговым ограничением &amp;lt;math&amp;gt;T_0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Соответственно, итоговая сложность фазы 1 &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P})+log_2\frac{N}{N_0}*d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Анализ фазы 2 проводится аналогично.&lt;br /&gt;
&lt;br /&gt;
Что касается операций ввода-вывода, то в фазе 1 данные сканируются один раз, а в фазе 2 не сканируются вовсе.&lt;br /&gt;
Некоторое количество вычислений связано с удалением точек из областей с низкой плотностью.&lt;br /&gt;
Если количество доступной для этой операции памяти не больше &#039;&#039;M&#039;&#039; и проведено порядка &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; перестроек дерева, то сложность ввода-вывода для фазы 1 существенно не отличается от сложности чтения из файла. Основываясь рассуждениях выше, сложность фаз 1 и 2 будет линейно увеличиваться с ростом N.&lt;br /&gt;
&lt;br /&gt;
В фазе 3 нет операций ввода-вывода. Её сложность ограничена константой, которая зависит от максимального размера входных данных, и варианта выбранного алгоритма для кластеризации. &lt;br /&gt;
&lt;br /&gt;
Фаза 4 снова сканирует данные и записывает каждую точку в подходящий кластер; время работы пропорционально &amp;lt;math&amp;gt;N*K&amp;lt;/math&amp;gt;.   &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Достоинства алгоритма ===&lt;br /&gt;
По сравнению с предыдущими методами BIRCH обладает следующими достоинствами:&lt;br /&gt;
&lt;br /&gt;
1. BIRCH является локальным алгоритмом, то есть каждое решение о каждом элементе кластера принимается без повторного сканирования данных или уже существующих кластеров. Используются только метрики, отражающие близость элементов друг к другу.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH использует факт неравномерного распределения данных в пространстве и поэтому не все данные рассматриваются как одинаково важные для построения кластера. Области с большой плотностью обрабатываются как единый кластер. Данные в более разреженных областях могут удаляться (опционально).&lt;br /&gt;
&lt;br /&gt;
3. BIRCH использует всю доступную память для получения наилучших из возможных подкластеров, в то же время минимизируя затраты на операции ввода/вывода. Оптимизация процесса кластеризации достигается за счет использования взвешенно-сбалансированного дерева. При этом время исполнения линейно.&lt;br /&gt;
&lt;br /&gt;
4. BIRCH не требует всего набора данных заранее (при этом просматривает его всего один раз).&lt;br /&gt;
&lt;br /&gt;
=== Недостатки алгоритма ===&lt;br /&gt;
&lt;br /&gt;
1. Работа только с числовыми данными&lt;br /&gt;
&lt;br /&gt;
2. BIRCH хорошо выделяет только кластеры сферической формы&lt;br /&gt;
&lt;br /&gt;
3. Существует необходимость в задании пороговых значений&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&lt;br /&gt;
[1] Википедия&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;/div&gt;</summary>
		<author><name>Светлана Морозова</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13496</id>
		<title>Участник:Smirnov.maxim/BIRCH</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13496"/>
		<updated>2016-10-23T09:36:34Z</updated>

		<summary type="html">&lt;p&gt;Светлана Морозова: /* Свойства алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Нахождение полезных для анализа закономерностей в больших объёмах данных с недавних пор вызывает значительный интерес. В связи с этим ввелось и стало активно развиваться такое понятие как &#039;&#039;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7 кластеризация]&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Ранние работы и алгоритмы, разработанные в этой области, не уделяли достаточного внимания анализу очень больших наборов данных или минимизации издержек на процессы ввода-вывода.&lt;br /&gt;
Решением этих проблем стал алгоритм, известный как BIRCH.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIRCH&#039;&#039;&#039; (balanced iterative reducing and clustering using hierarchies)- алгоритм, применяемый в области [https://ru.wikipedia.org/wiki/Data_mining Data mining] и использующий принципы [https://ru.wikipedia.org/wiki/%D0%98%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F иерархической кластеризации].&lt;br /&gt;
&lt;br /&gt;
Если имеется очень большой набор данных, то в пространстве он распределен, как правило, неравномерно. Кластерный анализ определяет места наибольшего и наименьшего скоплений, чтобы таким образом понять всю картину целиком. Кроме того, полученные кластеры визуализируются гораздо нагляднее, чем начальные &amp;quot;сырые&amp;quot; данные.&lt;br /&gt;
Задачей алгоритмов кластеризации является не только простое разбиение данных на кластеры, но и работа в рамках ограниченного объёма доступной памяти (как правило, её объём гораздо меньше, чем размер исходного набора данных) и минимизация времени, требуемого на операции ввода-вывода.&lt;br /&gt;
&lt;br /&gt;
Для наилучшего решения этих проблем BIRCH распределяет входящие данные по кластерам динамически. Для эффективной кластеризации алгоритму требуется всего одно сканирование данных (т.е. с увеличением количества данных сложность увеличивается линейно). А при помощи одной (или более) дополнительных итераций можно и далее улучшать эффективность. BIRCH также является первым алгоритмом, предложенным для эффективного управления &amp;quot;шумами&amp;quot; (данными, которые не вписываются в общее представление модели).&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Теоретическая основа ===&lt;br /&gt;
&lt;br /&gt;
Пусть в кластере имеются &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}, i=1,2,...,N&amp;lt;/math&amp;gt;.&lt;br /&gt;
Тогда &#039;&#039;&#039;центроид&#039;&#039;&#039; &amp;lt;math&amp;gt;{\vec{{X_0}}}&amp;lt;/math&amp;gt;, &#039;&#039;&#039;радиус&#039;&#039;&#039; &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &#039;&#039;&#039;диаметр&#039;&#039;&#039; &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластера определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;{\vec{X_0}}=\frac{\sum_{i=1}^N\vec{X_i}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{\sum_{i=1}^N{(\vec{X_i} - \vec{X_0})}^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{\sum_{i=1}^N\sum_{j=1}^N{(\vec{X_i} - \vec{X_j})}^2}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; - это среднее расстояние от каждой точки до центроида. &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; - это среднее расстояние между парами в кластере. Данные величины являются альтернативными метриками плотности кластера относительно центроида.&lt;br /&gt;
&lt;br /&gt;
Для измерения близости друг к другу двух кластеров вводятся следующие метрики:&lt;br /&gt;
&lt;br /&gt;
пусть даны центроиды двух кластеров &amp;lt;math&amp;gt;\vec{X_{01}}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\vec{X_{02}}&amp;lt;/math&amp;gt;.&lt;br /&gt;
Евклидова метрика &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt; и метрика Манхэттена &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt; между двумя кластерами определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_0 = ((\vec{X_{01}}-\vec{X_{02}})^2)^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_1 = |\vec{X_{01}}-\vec{X_{02}}| = \sum_{i=1}^d |{\vec{X_{01}}}^{(i)}-{\vec{X_{02}}}^{(i)}| &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть имеются два кластера, содержащих соответственно  &amp;lt;math&amp;gt;N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;N_2&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i= 1,2, ...,N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\{\vec{X_j}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j= N_1+1,N_1+2, ...,N_1+N_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Среднее расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &#039;&#039;&#039;среднее внутрикластерное расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &#039;&#039;&#039;дисперсия&#039;&#039;&#039; &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; для двух кластеров определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{\sum_{i=1}^{N_1}\sum_{j=N_1+1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{N_1N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{\sum_{i=1}^{N_1+N_2}\sum_{j=1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_4 = \sum_{k=1}^{N_1+N_2}(\vec{X_k} - \frac{\sum_{i=1}^{N_1+N_2}\vec{X_i}}{N_1+N_2})^2 - \sum_{i=1}^{N_1}(\vec{X_i} - \frac{\sum_{i=1}^{N_1}\vec{X_i}}{N_1})^2 - \sum_{j=N_1+1}^{N_1+N_2}(\vec{X_j} - \frac{\sum_{i=N_1+1}^{N_1+N_2}\vec{X_i}}{N_2})^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Таким образом, величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; относятся к отдельным кластерам, а &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; - к объединению двух кластеров.&lt;br /&gt;
&lt;br /&gt;
=== Кластерный элемент и кластерное дерево ===&lt;br /&gt;
&lt;br /&gt;
В основе концепции алгоритма BIRCH лежат понятия &#039;&#039;&#039;кластерного элемента&#039;&#039;&#039; и &#039;&#039;&#039;кластерного дерева (CF Tree)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====Кластерный элемент ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; Пусть в кластере содержатся  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности  &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;:&amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;i=1,2,...,N&amp;lt;/math&amp;gt;. &lt;br /&gt;
&#039;&#039;&#039;Кластерный элемент (CF)&#039;&#039;&#039; - тройка чисел, характеризующая информацию о кластере: &lt;br /&gt;
&amp;lt;math&amp;gt;CF = (N, \vec{LS}, SS)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - количество элементов входных данных, содержащихся в кластере, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; - линейная сумма входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}\vec{X_i}&amp;lt;/math&amp;gt;), &amp;lt;math&amp;gt;SS&amp;lt;/math&amp;gt; - сумма квадратов входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}{\vec{X_i}}^2&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Теорема&#039;&#039;&#039; Пусть &amp;lt;math&amp;gt;CF_1 = (N_1, \vec{LS_1}, SS_1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;CF_2 = (N_1, \vec{LS_2}, SS_2)&amp;lt;/math&amp;gt; - CF векторы двух непересекающихся кластеров. Тогда при их объединении образуется кластер со следующим CF вектором: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF = CF_1 + CF_2 = (N_1+N_2, \vec{LS_1}+\vec{LS_2}, SS_1+SS_2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Из указанных выше определения и теоремы вытекает тот факт, что при объединении кластеров их CF вектор может вычисляться инкрементно и точно. &lt;br /&gt;
Легко показать, что вычислить величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;, как и обычные метрики, также не составит труда.&lt;br /&gt;
&lt;br /&gt;
Таким образом, в данном случае информацией о кластере является не весь набор точек, а вектор CF. Хранение одного только вектора может показаться неэффективным, но этого вполне достаточно для оперирования всеми необходимыми метриками, на основе которых принимаются решения в алгоритме BIRCH.&lt;br /&gt;
&lt;br /&gt;
==== Кластерное дерево ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; &#039;&#039;&#039;Кластерное дерево (CF Tree)&#039;&#039;&#039; - это взвешенно сбалансированное дерево с двумя параметрами: &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - коэффициент разветвления, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - пороговая величина. Каждый нелистьевой узел дерева имеет не более чем &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; вхождений узлов следующей формы: &amp;lt;math&amp;gt;[CF_i,child_i]&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i=1,2,...,B&amp;lt;/math&amp;gt;, &#039;&#039;child&#039;&#039; - указатель на i-й дочерний узел, &amp;lt;math&amp;gt;CF_i&amp;lt;/math&amp;gt; - CF вектор соответствующего подкластера.&lt;br /&gt;
&lt;br /&gt;
Каждый листьевой узел имеет ссылку на два соседних узла (&#039;&#039;prev&#039;&#039; и &#039;&#039;next&#039;&#039;) для того, чтобы связать все узлы для эффективного сканирования.&lt;br /&gt;
Все листьевые узлы должны удовлетворять пороговому ограничению &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, т.е. диаметр (радиус) не должен превосходить &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;.&lt;br /&gt;
В процессе вставки новых данных CF дерево строится динамически. Оно использует вставку данных для кластеризации точно также как &amp;lt;math&amp;gt;B+&amp;lt;/math&amp;gt; [https://ru.wikipedia.org/wiki/B%2B-%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE дерево] использует её для поиска.&lt;br /&gt;
CF дерево очень компактно, поскольку каждый листьевой узел - это не просто точка, а подкластер (который объединяет множество точек с учётом ограничения &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Операция вставки в &#039;&#039;&#039;CF&#039;&#039;&#039; дерево ====&lt;br /&gt;
&lt;br /&gt;
Опишем алгоритм вставки элемнта &amp;lt;math&amp;gt;Ent&amp;lt;/math&amp;gt; в CF дерево:&lt;br /&gt;
&lt;br /&gt;
1) &#039;&#039;Определение подходящего листа&#039;&#039;: Начиная с корня, алгоритм рекурсивно спускается по CF дереву, выбирая &#039;&#039;&#039;ближайший&#039;&#039;&#039; дочерний узел в соответствии с выбранной метрикой &amp;lt;math&amp;gt;D0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D4&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &#039;&#039;Преобразование листа&#039;&#039;: Когда алгоритм доходит до листа, он находит ближайшую листьевой элемент, скажем, &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;, а затем проверяет, можно ли добавить &#039;&#039;Ent&#039;&#039; к &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt; без нарушения порогового условия. Если да, то с учётом этого изменяется CF вектор для &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;; если нет, то &#039;&#039;Ent&#039;&#039; становится новым элементом листа. Если в листе для этого достаточно места, то шаг окончен, иначе он должен &amp;quot;расщепиться&amp;quot;. Расщепление узла производится при помощи выбора за основу наиболее удалённой друг от друга пары элементов и перераспределение оставшихся элементов в соответствии с выбранным критерием близости.&lt;br /&gt;
&lt;br /&gt;
3) &#039;&#039;Преобразование пути к листу&#039;&#039;: После вставки &#039;&#039;Ent&#039;&#039; в лист мы должны обновить информацию о CF для каждого нелистьевого элемента на пути к листу. При отсутствии расщепления это означает простое сложение CF векторов для отражения факта добавления &#039;&#039;Ent&#039;&#039;. Расщепление листа же требует вставки нового нелистьевого элемента в родительский узел для задания только что созданного листа. Если у родителя есть место для этого элемента, то необходимо просто преобразовать CF векторы на всех более высоких уровнях. В общем случае, однако, нам также придётся расщепить родительский узел, и так далее до корня. Если расщеплён корень, то высота дерева увеличивается на единицу.&lt;br /&gt;
&lt;br /&gt;
4) &#039;&#039;Улучшение слияния&#039;&#039;: Расщепление вызвано ограничением на размер узла, который не зависит от кластеризационных свойств данных. Если во входящем потоке присутствуют &amp;quot;искажённые&amp;quot; (из областей с низкой плотностью) данные, это может повлиять на качество кластеризации, а также уменьшить эффективность использования памяти. Дополнительный шаг алгоритма помогает решить эти проблемы: предположим, что произошло расщепление листа, и распространение этого процесса остановилось на некотором нелистьевом узле &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt;, то есть &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; может вместить дополнительный элемент, полученный после расщепления. Теперь мы сканируем узел &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; для нахождения двух наиболее близких элементов. Если это не пара, отвечающая расщеплению, мы пытаемся объединить их и поставить в соответствие два дочерних узла. Если количество элементов в дочерних узлах  больше B, мы снова расщепляем результат объединения.&lt;br /&gt;
В процессе повторного расщепления, в случае, если один источник собирает достаточно элементов для того, чтобы полностью заполнить узел, оставшиеся элементы передаются другом источнику. В итоге, если объединённые элементы помещаются в одном узле, в нём освобождается место для ещё одного элемента. Тем самым увеличивается степень использования свободного пространства и откладывается дальнейшее расщепление. В ином случае мы улучшаем распределение элементов в двух ближайших подкластерах.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро алгоритма заключается в многократном выполнении операции вставки нового элемента в дерево, в процессе чего требуется вычисление следующих величин:&lt;br /&gt;
&lt;br /&gt;
* радиуса &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; или диаметра &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластерного элемента. Выполняется при попытке вставить новый элемент в один из подкластеров листьевого узла дерева.&lt;br /&gt;
&lt;br /&gt;
* расстояния между двумя элементами. Выполняется при поиске ближайшего по отношению к новому элементу подкластера в узле дерева по одной из рассмотренных в разд. 1.2.1 метрик &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Зная характеристики кластерных элементов &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;, в результате алгебраических преобразований можно получить следующие упрощенные формулы вычисления необходимых значений:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\vec{X_0} = \frac{\vec{LS}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{SS - 2\vec{X_0}\vec{LS} + N(\vec{X_0})^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{2(N*SS - (\vec{LS})^2)}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{N_1*SS_2 + N_2*SS_1 - 2\vec{LS_1}\vec{LS_2}}{N_1*N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{2((N_1+N_2)(SS_1+SS_2)-(\vec{LS_1}+\vec{LS_2})^2)}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Реализация алгоритма BIRCH состояит из следующих четырёх фаз:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 1&#039;&#039;&#039;. Главной задачей фазы 1 является сканирование всех данных и построение в памяти исходного CF дерева, используя заданное количество памяти. Это дерево стремится отразить информацию о кластеризации данных настолько хорошо, насколько это позволяют ограничения по памяти. При этом плотно распределённые данные группируются в подкластеры, а более разрозненные данные удаляются. После завершения фазы 1 вспомогательные вычисления в дальнейших фазах будут:&lt;br /&gt;
&lt;br /&gt;
1) быстрее, потому что (а) больше не нужны операции ввода-вывода, (b) проблема кластеризации начальных данных упрощается до проблемы кластеризации подкластеров в листьях;&lt;br /&gt;
&lt;br /&gt;
2) точнее, потому что (а) большинство данных с низкой плотностью удалены, (b) оставшиеся данные распределены оптимально (в соответствии с доступным количеством памяти);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 2&#039;&#039;&#039;. Данная фаза является опциональной. Известно, что существующие методы глобальной кластеризации, используемые в рамках фазы 3, имеют различные диапазоны входных значений, при которых их реализация наиболее эффективна. Поэтому потенциально существует пробел между размером фазы 1 и входными значениями фазы 3. И фаза 2 как раз является недостающим связующим звеном: так же как и фаза 1, она сканирует листьевые элементы начального CF дерева для того, чтобы построить меньшее дерево, удаляя ещё больше элементов с низкой плотностью и группируя переполненные подкластеры в большие кластеры.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 3&#039;&#039;&#039;. В данной фазе для листьевых элементов применяется (любой подходящий) алгоритм глобальной кластеризации. Существующие алгоритмы кластеризации наборов точек могут также работать с наборами подкластеров, каждый из которых представлен своим CF вектором. Зная CF вектор, можно вычислить центроид и в дальнейшем заменить всю информацию о кластере этим значением (этого достаточно для вычисления большинства необходимых метрик). После фазы 3 мы получаем набор кластеров, который отражает основные характеристики распределяемых данных.&lt;br /&gt;
Однако, всё ещё могут оставаться некоторые неточности, для устранения которых существует фаза 4.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 4&#039;&#039;&#039;. Данная фаза является опциональной и влечёт за собой затраты на дополнительное сканирование данных для корректировки неточностей и дальнейшего улучшения кластеризации. Фаза 4 использует центроиды кластеров, полученные в фазе 3 для как основы и перераспределяет точки входных данных в ближайшие для них основы для получения нового списка кластеров. Фаза 4, если это необходимо пользователю, может быть расширена дополнительными проходами для уверенности в том, что результат приближается к оптимальному.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Для начала проанализируем вычислительную сложность фазы 1.&lt;br /&gt;
Максимальный размер дерева &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt;. Для того чтобы вставить элемент, мы должны пройти путь от корня до листа (это около &amp;lt;math&amp;gt;1+log_B\frac{M}{P}&amp;lt;/math&amp;gt; узлов). В каждом узле в поисках &amp;quot;ближайшего&amp;quot; нам необходимо просмотреть B элементов; сложность для каждого элемента пропорциональна размерности &#039;&#039;d&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Поэтому сложность вставки всех входных точек &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В случае, когда необходимо перестроить дерево, предположим, что ES - это размер CF элемента. Существует максимум &amp;lt;math&amp;gt;\frac{M}{ES}&amp;lt;/math&amp;gt; листьевых элементов для вставки, поэтому сложность повторной вставки листьевых элементов &amp;lt;math&amp;gt;O(d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Количество итераций перестройки дерева зависит от пороговой величины. На самом деле, это около &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; (двоичное основание появилось из-за того, что мы не можем провести оценку более чем в 2 раза отличающуюся от текущего размера). &amp;lt;math&amp;gt;N_0&amp;lt;/math&amp;gt; - это число входных точек, загруженных в память с пороговым ограничением &amp;lt;math&amp;gt;T_0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Соответственно, итоговая сложность фазы 1 &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P})+log_2\frac{N}{N_0}*d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Анализ фазы 2 проводится аналогично.&lt;br /&gt;
&lt;br /&gt;
Что касается операций ввода-вывода, то в фазе 1 данные сканируются один раз, а в фазе 2 не сканируются вовсе.&lt;br /&gt;
Некоторое количество вычислений связано с удалением точек из областей с низкой плотностью.&lt;br /&gt;
Если количество доступной для этой операции памяти не больше &#039;&#039;M&#039;&#039; и проведено порядка &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; перестроек дерева, то сложность ввода-вывода для фазы 1 существенно не отличается от сложности чтения из файла. Основываясь рассуждениях выше, сложность фаз 1 и 2 будет линейно увеличиваться с ростом N.&lt;br /&gt;
&lt;br /&gt;
В фазе 3 нет операций ввода-вывода. Её сложность ограничена константой, которая зависит от максимального размера входных данных, и варианта выбранного алгоритма для кластеризации. &lt;br /&gt;
&lt;br /&gt;
Фаза 4 снова сканирует данные и записывает каждую точку в подходящий кластер; время работы пропорционально &amp;lt;math&amp;gt;N*K&amp;lt;/math&amp;gt;.   &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Достоинства алгоритма ===&lt;br /&gt;
По сравнению с предыдущими методами BIRCH обладает следующими достоинствами:&lt;br /&gt;
&lt;br /&gt;
1. BIRCH является локальным алгоритмом, то есть каждое решение о каждом элементе кластера принимается без повторного сканирования данных или уже существующих кластеров. Используются только метрики, отражающие близость элементов друг к другу.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH использует факт неравномерного распределения данных в пространстве и поэтому не все данные рассматриваются как одинаково важные для построения кластера. Области с большой плотностью обрабатываются как единый кластер. Данные в более разреженных областях могут удаляться (опционально).&lt;br /&gt;
&lt;br /&gt;
3. BIRCH использует всю доступную память для получения наилучших из возможных подкластеров, в то же время минимизируя затраты на операции ввода/вывода. Оптимизация процесса кластеризации достигается за счет использования взвешенно-сбалансированного дерева. При этом время исполнения линейно.&lt;br /&gt;
&lt;br /&gt;
4. BIRCH не требует всего набора данных заранее (при этом просматривает его всего один раз).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Недостатки алгоритма ===&lt;br /&gt;
&lt;br /&gt;
1. Работа только с числовыми данными&lt;br /&gt;
&lt;br /&gt;
2. BIRCH хорошо выделяет только кластеры сферической формы&lt;br /&gt;
&lt;br /&gt;
3. Существует необходимость в задании пороговых значений&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&lt;br /&gt;
[1] Википедия&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;/div&gt;</summary>
		<author><name>Светлана Морозова</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13495</id>
		<title>Участник:Smirnov.maxim/BIRCH</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13495"/>
		<updated>2016-10-23T09:32:45Z</updated>

		<summary type="html">&lt;p&gt;Светлана Морозова: /* Последовательная сложность алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Нахождение полезных для анализа закономерностей в больших объёмах данных с недавних пор вызывает значительный интерес. В связи с этим ввелось и стало активно развиваться такое понятие как &#039;&#039;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7 кластеризация]&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Ранние работы и алгоритмы, разработанные в этой области, не уделяли достаточного внимания анализу очень больших наборов данных или минимизации издержек на процессы ввода-вывода.&lt;br /&gt;
Решением этих проблем стал алгоритм, известный как BIRCH.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIRCH&#039;&#039;&#039; (balanced iterative reducing and clustering using hierarchies)- алгоритм, применяемый в области [https://ru.wikipedia.org/wiki/Data_mining Data mining] и использующий принципы [https://ru.wikipedia.org/wiki/%D0%98%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F иерархической кластеризации].&lt;br /&gt;
&lt;br /&gt;
Если имеется очень большой набор данных, то в пространстве он распределен, как правило, неравномерно. Кластерный анализ определяет места наибольшего и наименьшего скоплений, чтобы таким образом понять всю картину целиком. Кроме того, полученные кластеры визуализируются гораздо нагляднее, чем начальные &amp;quot;сырые&amp;quot; данные.&lt;br /&gt;
Задачей алгоритмов кластеризации является не только простое разбиение данных на кластеры, но и работа в рамках ограниченного объёма доступной памяти (как правило, её объём гораздо меньше, чем размер исходного набора данных) и минимизация времени, требуемого на операции ввода-вывода.&lt;br /&gt;
&lt;br /&gt;
Для наилучшего решения этих проблем BIRCH распределяет входящие данные по кластерам динамически. Для эффективной кластеризации алгоритму требуется всего одно сканирование данных (т.е. с увеличением количества данных сложность увеличивается линейно). А при помощи одной (или более) дополнительных итераций можно и далее улучшать эффективность. BIRCH также является первым алгоритмом, предложенным для эффективного управления &amp;quot;шумами&amp;quot; (данными, которые не вписываются в общее представление модели).&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Теоретическая основа ===&lt;br /&gt;
&lt;br /&gt;
Пусть в кластере имеются &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}, i=1,2,...,N&amp;lt;/math&amp;gt;.&lt;br /&gt;
Тогда &#039;&#039;&#039;центроид&#039;&#039;&#039; &amp;lt;math&amp;gt;{\vec{{X_0}}}&amp;lt;/math&amp;gt;, &#039;&#039;&#039;радиус&#039;&#039;&#039; &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &#039;&#039;&#039;диаметр&#039;&#039;&#039; &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластера определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;{\vec{X_0}}=\frac{\sum_{i=1}^N\vec{X_i}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{\sum_{i=1}^N{(\vec{X_i} - \vec{X_0})}^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{\sum_{i=1}^N\sum_{j=1}^N{(\vec{X_i} - \vec{X_j})}^2}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; - это среднее расстояние от каждой точки до центроида. &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; - это среднее расстояние между парами в кластере. Данные величины являются альтернативными метриками плотности кластера относительно центроида.&lt;br /&gt;
&lt;br /&gt;
Для измерения близости друг к другу двух кластеров вводятся следующие метрики:&lt;br /&gt;
&lt;br /&gt;
пусть даны центроиды двух кластеров &amp;lt;math&amp;gt;\vec{X_{01}}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\vec{X_{02}}&amp;lt;/math&amp;gt;.&lt;br /&gt;
Евклидова метрика &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt; и метрика Манхэттена &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt; между двумя кластерами определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_0 = ((\vec{X_{01}}-\vec{X_{02}})^2)^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_1 = |\vec{X_{01}}-\vec{X_{02}}| = \sum_{i=1}^d |{\vec{X_{01}}}^{(i)}-{\vec{X_{02}}}^{(i)}| &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть имеются два кластера, содержащих соответственно  &amp;lt;math&amp;gt;N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;N_2&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i= 1,2, ...,N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\{\vec{X_j}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j= N_1+1,N_1+2, ...,N_1+N_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Среднее расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &#039;&#039;&#039;среднее внутрикластерное расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &#039;&#039;&#039;дисперсия&#039;&#039;&#039; &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; для двух кластеров определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{\sum_{i=1}^{N_1}\sum_{j=N_1+1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{N_1N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{\sum_{i=1}^{N_1+N_2}\sum_{j=1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_4 = \sum_{k=1}^{N_1+N_2}(\vec{X_k} - \frac{\sum_{i=1}^{N_1+N_2}\vec{X_i}}{N_1+N_2})^2 - \sum_{i=1}^{N_1}(\vec{X_i} - \frac{\sum_{i=1}^{N_1}\vec{X_i}}{N_1})^2 - \sum_{j=N_1+1}^{N_1+N_2}(\vec{X_j} - \frac{\sum_{i=N_1+1}^{N_1+N_2}\vec{X_i}}{N_2})^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Таким образом, величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; относятся к отдельным кластерам, а &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; - к объединению двух кластеров.&lt;br /&gt;
&lt;br /&gt;
=== Кластерный элемент и кластерное дерево ===&lt;br /&gt;
&lt;br /&gt;
В основе концепции алгоритма BIRCH лежат понятия &#039;&#039;&#039;кластерного элемента&#039;&#039;&#039; и &#039;&#039;&#039;кластерного дерева (CF Tree)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====Кластерный элемент ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; Пусть в кластере содержатся  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности  &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;:&amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;i=1,2,...,N&amp;lt;/math&amp;gt;. &lt;br /&gt;
&#039;&#039;&#039;Кластерный элемент (CF)&#039;&#039;&#039; - тройка чисел, характеризующая информацию о кластере: &lt;br /&gt;
&amp;lt;math&amp;gt;CF = (N, \vec{LS}, SS)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - количество элементов входных данных, содержащихся в кластере, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; - линейная сумма входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}\vec{X_i}&amp;lt;/math&amp;gt;), &amp;lt;math&amp;gt;SS&amp;lt;/math&amp;gt; - сумма квадратов входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}{\vec{X_i}}^2&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Теорема&#039;&#039;&#039; Пусть &amp;lt;math&amp;gt;CF_1 = (N_1, \vec{LS_1}, SS_1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;CF_2 = (N_1, \vec{LS_2}, SS_2)&amp;lt;/math&amp;gt; - CF векторы двух непересекающихся кластеров. Тогда при их объединении образуется кластер со следующим CF вектором: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF = CF_1 + CF_2 = (N_1+N_2, \vec{LS_1}+\vec{LS_2}, SS_1+SS_2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Из указанных выше определения и теоремы вытекает тот факт, что при объединении кластеров их CF вектор может вычисляться инкрементно и точно. &lt;br /&gt;
Легко показать, что вычислить величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;, как и обычные метрики, также не составит труда.&lt;br /&gt;
&lt;br /&gt;
Таким образом, в данном случае информацией о кластере является не весь набор точек, а вектор CF. Хранение одного только вектора может показаться неэффективным, но этого вполне достаточно для оперирования всеми необходимыми метриками, на основе которых принимаются решения в алгоритме BIRCH.&lt;br /&gt;
&lt;br /&gt;
==== Кластерное дерево ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; &#039;&#039;&#039;Кластерное дерево (CF Tree)&#039;&#039;&#039; - это взвешенно сбалансированное дерево с двумя параметрами: &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - коэффициент разветвления, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - пороговая величина. Каждый нелистьевой узел дерева имеет не более чем &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; вхождений узлов следующей формы: &amp;lt;math&amp;gt;[CF_i,child_i]&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i=1,2,...,B&amp;lt;/math&amp;gt;, &#039;&#039;child&#039;&#039; - указатель на i-й дочерний узел, &amp;lt;math&amp;gt;CF_i&amp;lt;/math&amp;gt; - CF вектор соответствующего подкластера.&lt;br /&gt;
&lt;br /&gt;
Каждый листьевой узел имеет ссылку на два соседних узла (&#039;&#039;prev&#039;&#039; и &#039;&#039;next&#039;&#039;) для того, чтобы связать все узлы для эффективного сканирования.&lt;br /&gt;
Все листьевые узлы должны удовлетворять пороговому ограничению &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, т.е. диаметр (радиус) не должен превосходить &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;.&lt;br /&gt;
В процессе вставки новых данных CF дерево строится динамически. Оно использует вставку данных для кластеризации точно также как &amp;lt;math&amp;gt;B+&amp;lt;/math&amp;gt; [https://ru.wikipedia.org/wiki/B%2B-%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE дерево] использует её для поиска.&lt;br /&gt;
CF дерево очень компактно, поскольку каждый листьевой узел - это не просто точка, а подкластер (который объединяет множество точек с учётом ограничения &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Операция вставки в &#039;&#039;&#039;CF&#039;&#039;&#039; дерево ====&lt;br /&gt;
&lt;br /&gt;
Опишем алгоритм вставки элемнта &amp;lt;math&amp;gt;Ent&amp;lt;/math&amp;gt; в CF дерево:&lt;br /&gt;
&lt;br /&gt;
1) &#039;&#039;Определение подходящего листа&#039;&#039;: Начиная с корня, алгоритм рекурсивно спускается по CF дереву, выбирая &#039;&#039;&#039;ближайший&#039;&#039;&#039; дочерний узел в соответствии с выбранной метрикой &amp;lt;math&amp;gt;D0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D4&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &#039;&#039;Преобразование листа&#039;&#039;: Когда алгоритм доходит до листа, он находит ближайшую листьевой элемент, скажем, &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;, а затем проверяет, можно ли добавить &#039;&#039;Ent&#039;&#039; к &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt; без нарушения порогового условия. Если да, то с учётом этого изменяется CF вектор для &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;; если нет, то &#039;&#039;Ent&#039;&#039; становится новым элементом листа. Если в листе для этого достаточно места, то шаг окончен, иначе он должен &amp;quot;расщепиться&amp;quot;. Расщепление узла производится при помощи выбора за основу наиболее удалённой друг от друга пары элементов и перераспределение оставшихся элементов в соответствии с выбранным критерием близости.&lt;br /&gt;
&lt;br /&gt;
3) &#039;&#039;Преобразование пути к листу&#039;&#039;: После вставки &#039;&#039;Ent&#039;&#039; в лист мы должны обновить информацию о CF для каждого нелистьевого элемента на пути к листу. При отсутствии расщепления это означает простое сложение CF векторов для отражения факта добавления &#039;&#039;Ent&#039;&#039;. Расщепление листа же требует вставки нового нелистьевого элемента в родительский узел для задания только что созданного листа. Если у родителя есть место для этого элемента, то необходимо просто преобразовать CF векторы на всех более высоких уровнях. В общем случае, однако, нам также придётся расщепить родительский узел, и так далее до корня. Если расщеплён корень, то высота дерева увеличивается на единицу.&lt;br /&gt;
&lt;br /&gt;
4) &#039;&#039;Улучшение слияния&#039;&#039;: Расщепление вызвано ограничением на размер узла, который не зависит от кластеризационных свойств данных. Если во входящем потоке присутствуют &amp;quot;искажённые&amp;quot; (из областей с низкой плотностью) данные, это может повлиять на качество кластеризации, а также уменьшить эффективность использования памяти. Дополнительный шаг алгоритма помогает решить эти проблемы: предположим, что произошло расщепление листа, и распространение этого процесса остановилось на некотором нелистьевом узле &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt;, то есть &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; может вместить дополнительный элемент, полученный после расщепления. Теперь мы сканируем узел &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; для нахождения двух наиболее близких элементов. Если это не пара, отвечающая расщеплению, мы пытаемся объединить их и поставить в соответствие два дочерних узла. Если количество элементов в дочерних узлах  больше B, мы снова расщепляем результат объединения.&lt;br /&gt;
В процессе повторного расщепления, в случае, если один источник собирает достаточно элементов для того, чтобы полностью заполнить узел, оставшиеся элементы передаются другом источнику. В итоге, если объединённые элементы помещаются в одном узле, в нём освобождается место для ещё одного элемента. Тем самым увеличивается степень использования свободного пространства и откладывается дальнейшее расщепление. В ином случае мы улучшаем распределение элементов в двух ближайших подкластерах.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро алгоритма заключается в многократном выполнении операции вставки нового элемента в дерево, в процессе чего требуется вычисление следующих величин:&lt;br /&gt;
&lt;br /&gt;
* радиуса &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; или диаметра &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластерного элемента. Выполняется при попытке вставить новый элемент в один из подкластеров листьевого узла дерева.&lt;br /&gt;
&lt;br /&gt;
* расстояния между двумя элементами. Выполняется при поиске ближайшего по отношению к новому элементу подкластера в узле дерева по одной из рассмотренных в разд. 1.2.1 метрик &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Зная характеристики кластерных элементов &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;, в результате алгебраических преобразований можно получить следующие упрощенные формулы вычисления необходимых значений:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\vec{X_0} = \frac{\vec{LS}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{SS - 2\vec{X_0}\vec{LS} + N(\vec{X_0})^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{2(N*SS - (\vec{LS})^2)}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{N_1*SS_2 + N_2*SS_1 - 2\vec{LS_1}\vec{LS_2}}{N_1*N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{2((N_1+N_2)(SS_1+SS_2)-(\vec{LS_1}+\vec{LS_2})^2)}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Реализация алгоритма BIRCH состояит из следующих четырёх фаз:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 1&#039;&#039;&#039;. Главной задачей фазы 1 является сканирование всех данных и построение в памяти исходного CF дерева, используя заданное количество памяти. Это дерево стремится отразить информацию о кластеризации данных настолько хорошо, насколько это позволяют ограничения по памяти. При этом плотно распределённые данные группируются в подкластеры, а более разрозненные данные удаляются. После завершения фазы 1 вспомогательные вычисления в дальнейших фазах будут:&lt;br /&gt;
&lt;br /&gt;
1) быстрее, потому что (а) больше не нужны операции ввода-вывода, (b) проблема кластеризации начальных данных упрощается до проблемы кластеризации подкластеров в листьях;&lt;br /&gt;
&lt;br /&gt;
2) точнее, потому что (а) большинство данных с низкой плотностью удалены, (b) оставшиеся данные распределены оптимально (в соответствии с доступным количеством памяти);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 2&#039;&#039;&#039;. Данная фаза является опциональной. Известно, что существующие методы глобальной кластеризации, используемые в рамках фазы 3, имеют различные диапазоны входных значений, при которых их реализация наиболее эффективна. Поэтому потенциально существует пробел между размером фазы 1 и входными значениями фазы 3. И фаза 2 как раз является недостающим связующим звеном: так же как и фаза 1, она сканирует листьевые элементы начального CF дерева для того, чтобы построить меньшее дерево, удаляя ещё больше элементов с низкой плотностью и группируя переполненные подкластеры в большие кластеры.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 3&#039;&#039;&#039;. В данной фазе для листьевых элементов применяется (любой подходящий) алгоритм глобальной кластеризации. Существующие алгоритмы кластеризации наборов точек могут также работать с наборами подкластеров, каждый из которых представлен своим CF вектором. Зная CF вектор, можно вычислить центроид и в дальнейшем заменить всю информацию о кластере этим значением (этого достаточно для вычисления большинства необходимых метрик). После фазы 3 мы получаем набор кластеров, который отражает основные характеристики распределяемых данных.&lt;br /&gt;
Однако, всё ещё могут оставаться некоторые неточности, для устранения которых существует фаза 4.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 4&#039;&#039;&#039;. Данная фаза является опциональной и влечёт за собой затраты на дополнительное сканирование данных для корректировки неточностей и дальнейшего улучшения кластеризации. Фаза 4 использует центроиды кластеров, полученные в фазе 3 для как основы и перераспределяет точки входных данных в ближайшие для них основы для получения нового списка кластеров. Фаза 4, если это необходимо пользователю, может быть расширена дополнительными проходами для уверенности в том, что результат приближается к оптимальному.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Для начала проанализируем вычислительную сложность фазы 1.&lt;br /&gt;
Максимальный размер дерева &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt;. Для того чтобы вставить элемент, мы должны пройти путь от корня до листа (это около &amp;lt;math&amp;gt;1+log_B\frac{M}{P}&amp;lt;/math&amp;gt; узлов). В каждом узле в поисках &amp;quot;ближайшего&amp;quot; нам необходимо просмотреть B элементов; сложность для каждого элемента пропорциональна размерности &#039;&#039;d&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Поэтому сложность вставки всех входных точек &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В случае, когда необходимо перестроить дерево, предположим, что ES - это размер CF элемента. Существует максимум &amp;lt;math&amp;gt;\frac{M}{ES}&amp;lt;/math&amp;gt; листьевых элементов для вставки, поэтому сложность повторной вставки листьевых элементов &amp;lt;math&amp;gt;O(d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Количество итераций перестройки дерева зависит от пороговой величины. На самом деле, это около &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; (двоичное основание появилось из-за того, что мы не можем провести оценку более чем в 2 раза отличающуюся от текущего размера). &amp;lt;math&amp;gt;N_0&amp;lt;/math&amp;gt; - это число входных точек, загруженных в память с пороговым ограничением &amp;lt;math&amp;gt;T_0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Соответственно, итоговая сложность фазы 1 &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P})+log_2\frac{N}{N_0}*d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Анализ фазы 2 проводится аналогично.&lt;br /&gt;
&lt;br /&gt;
Что касается операций ввода-вывода, то в фазе 1 данные сканируются один раз, а в фазе 2 не сканируются вовсе.&lt;br /&gt;
Некоторое количество вычислений связано с удалением точек из областей с низкой плотностью.&lt;br /&gt;
Если количество доступной для этой операции памяти не больше &#039;&#039;M&#039;&#039; и проведено порядка &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; перестроек дерева, то сложность ввода-вывода для фазы 1 существенно не отличается от сложности чтения из файла. Основываясь рассуждениях выше, сложность фаз 1 и 2 будет линейно увеличиваться с ростом N.&lt;br /&gt;
&lt;br /&gt;
В фазе 3 нет операций ввода-вывода. Её сложность ограничена константой, которая зависит от максимального размера входных данных, и варианта выбранного алгоритма для кластеризации. &lt;br /&gt;
&lt;br /&gt;
Фаза 4 снова сканирует данные и записывает каждую точку в подходящий кластер; время работы пропорционально &amp;lt;math&amp;gt;N*K&amp;lt;/math&amp;gt;.   &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Достоинства алгоритма ===&lt;br /&gt;
По сравнению с предыдущими методами BIRCH обладает следующими достоинствами:&lt;br /&gt;
&lt;br /&gt;
1. BIRCH является локальным алгоритмом, то есть каждое решение о каждом элементе кластера принимается без повторного сканирования данных или уже существующих кластеров. Используются только метрики, отражающие близость элементов друг к другу.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH использует факт неравномерного распределения данных в пространстве и поэтому не все данные рассматриваются как одинаково важные для построения кластера. Области с большой плотностью обрабатываются как единый кластер. Данные в более разреженных областях могут удаляться (опционально).&lt;br /&gt;
&lt;br /&gt;
3. BIRCH использует всю доступную память для получения наилучших из возможных подкластеров, в то же время минимизируя затраты на операции ввода/вывода. Оптимизация процесса кластеризации достигается за счет использования взвешенно-сбалансированного дерева. При этом время исполнения линейно.&lt;br /&gt;
&lt;br /&gt;
4. BIRCH не требует всего набора данных заранее (при этом просматривает его всего один раз).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&lt;br /&gt;
[1] Википедия&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;/div&gt;</summary>
		<author><name>Светлана Морозова</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13494</id>
		<title>Участник:Smirnov.maxim/BIRCH</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13494"/>
		<updated>2016-10-23T09:31:24Z</updated>

		<summary type="html">&lt;p&gt;Светлана Морозова: /* Последовательная сложность алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Нахождение полезных для анализа закономерностей в больших объёмах данных с недавних пор вызывает значительный интерес. В связи с этим ввелось и стало активно развиваться такое понятие как &#039;&#039;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7 кластеризация]&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Ранние работы и алгоритмы, разработанные в этой области, не уделяли достаточного внимания анализу очень больших наборов данных или минимизации издержек на процессы ввода-вывода.&lt;br /&gt;
Решением этих проблем стал алгоритм, известный как BIRCH.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIRCH&#039;&#039;&#039; (balanced iterative reducing and clustering using hierarchies)- алгоритм, применяемый в области [https://ru.wikipedia.org/wiki/Data_mining Data mining] и использующий принципы [https://ru.wikipedia.org/wiki/%D0%98%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F иерархической кластеризации].&lt;br /&gt;
&lt;br /&gt;
Если имеется очень большой набор данных, то в пространстве он распределен, как правило, неравномерно. Кластерный анализ определяет места наибольшего и наименьшего скоплений, чтобы таким образом понять всю картину целиком. Кроме того, полученные кластеры визуализируются гораздо нагляднее, чем начальные &amp;quot;сырые&amp;quot; данные.&lt;br /&gt;
Задачей алгоритмов кластеризации является не только простое разбиение данных на кластеры, но и работа в рамках ограниченного объёма доступной памяти (как правило, её объём гораздо меньше, чем размер исходного набора данных) и минимизация времени, требуемого на операции ввода-вывода.&lt;br /&gt;
&lt;br /&gt;
Для наилучшего решения этих проблем BIRCH распределяет входящие данные по кластерам динамически. Для эффективной кластеризации алгоритму требуется всего одно сканирование данных (т.е. с увеличением количества данных сложность увеличивается линейно). А при помощи одной (или более) дополнительных итераций можно и далее улучшать эффективность. BIRCH также является первым алгоритмом, предложенным для эффективного управления &amp;quot;шумами&amp;quot; (данными, которые не вписываются в общее представление модели).&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Теоретическая основа ===&lt;br /&gt;
&lt;br /&gt;
Пусть в кластере имеются &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}, i=1,2,...,N&amp;lt;/math&amp;gt;.&lt;br /&gt;
Тогда &#039;&#039;&#039;центроид&#039;&#039;&#039; &amp;lt;math&amp;gt;{\vec{{X_0}}}&amp;lt;/math&amp;gt;, &#039;&#039;&#039;радиус&#039;&#039;&#039; &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &#039;&#039;&#039;диаметр&#039;&#039;&#039; &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластера определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;{\vec{X_0}}=\frac{\sum_{i=1}^N\vec{X_i}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{\sum_{i=1}^N{(\vec{X_i} - \vec{X_0})}^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{\sum_{i=1}^N\sum_{j=1}^N{(\vec{X_i} - \vec{X_j})}^2}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; - это среднее расстояние от каждой точки до центроида. &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; - это среднее расстояние между парами в кластере. Данные величины являются альтернативными метриками плотности кластера относительно центроида.&lt;br /&gt;
&lt;br /&gt;
Для измерения близости друг к другу двух кластеров вводятся следующие метрики:&lt;br /&gt;
&lt;br /&gt;
пусть даны центроиды двух кластеров &amp;lt;math&amp;gt;\vec{X_{01}}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\vec{X_{02}}&amp;lt;/math&amp;gt;.&lt;br /&gt;
Евклидова метрика &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt; и метрика Манхэттена &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt; между двумя кластерами определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_0 = ((\vec{X_{01}}-\vec{X_{02}})^2)^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_1 = |\vec{X_{01}}-\vec{X_{02}}| = \sum_{i=1}^d |{\vec{X_{01}}}^{(i)}-{\vec{X_{02}}}^{(i)}| &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть имеются два кластера, содержащих соответственно  &amp;lt;math&amp;gt;N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;N_2&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i= 1,2, ...,N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\{\vec{X_j}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j= N_1+1,N_1+2, ...,N_1+N_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Среднее расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &#039;&#039;&#039;среднее внутрикластерное расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &#039;&#039;&#039;дисперсия&#039;&#039;&#039; &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; для двух кластеров определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{\sum_{i=1}^{N_1}\sum_{j=N_1+1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{N_1N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{\sum_{i=1}^{N_1+N_2}\sum_{j=1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_4 = \sum_{k=1}^{N_1+N_2}(\vec{X_k} - \frac{\sum_{i=1}^{N_1+N_2}\vec{X_i}}{N_1+N_2})^2 - \sum_{i=1}^{N_1}(\vec{X_i} - \frac{\sum_{i=1}^{N_1}\vec{X_i}}{N_1})^2 - \sum_{j=N_1+1}^{N_1+N_2}(\vec{X_j} - \frac{\sum_{i=N_1+1}^{N_1+N_2}\vec{X_i}}{N_2})^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Таким образом, величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; относятся к отдельным кластерам, а &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; - к объединению двух кластеров.&lt;br /&gt;
&lt;br /&gt;
=== Кластерный элемент и кластерное дерево ===&lt;br /&gt;
&lt;br /&gt;
В основе концепции алгоритма BIRCH лежат понятия &#039;&#039;&#039;кластерного элемента&#039;&#039;&#039; и &#039;&#039;&#039;кластерного дерева (CF Tree)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====Кластерный элемент ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; Пусть в кластере содержатся  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности  &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;:&amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;i=1,2,...,N&amp;lt;/math&amp;gt;. &lt;br /&gt;
&#039;&#039;&#039;Кластерный элемент (CF)&#039;&#039;&#039; - тройка чисел, характеризующая информацию о кластере: &lt;br /&gt;
&amp;lt;math&amp;gt;CF = (N, \vec{LS}, SS)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - количество элементов входных данных, содержащихся в кластере, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; - линейная сумма входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}\vec{X_i}&amp;lt;/math&amp;gt;), &amp;lt;math&amp;gt;SS&amp;lt;/math&amp;gt; - сумма квадратов входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}{\vec{X_i}}^2&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Теорема&#039;&#039;&#039; Пусть &amp;lt;math&amp;gt;CF_1 = (N_1, \vec{LS_1}, SS_1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;CF_2 = (N_1, \vec{LS_2}, SS_2)&amp;lt;/math&amp;gt; - CF векторы двух непересекающихся кластеров. Тогда при их объединении образуется кластер со следующим CF вектором: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF = CF_1 + CF_2 = (N_1+N_2, \vec{LS_1}+\vec{LS_2}, SS_1+SS_2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Из указанных выше определения и теоремы вытекает тот факт, что при объединении кластеров их CF вектор может вычисляться инкрементно и точно. &lt;br /&gt;
Легко показать, что вычислить величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;, как и обычные метрики, также не составит труда.&lt;br /&gt;
&lt;br /&gt;
Таким образом, в данном случае информацией о кластере является не весь набор точек, а вектор CF. Хранение одного только вектора может показаться неэффективным, но этого вполне достаточно для оперирования всеми необходимыми метриками, на основе которых принимаются решения в алгоритме BIRCH.&lt;br /&gt;
&lt;br /&gt;
==== Кластерное дерево ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; &#039;&#039;&#039;Кластерное дерево (CF Tree)&#039;&#039;&#039; - это взвешенно сбалансированное дерево с двумя параметрами: &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - коэффициент разветвления, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - пороговая величина. Каждый нелистьевой узел дерева имеет не более чем &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; вхождений узлов следующей формы: &amp;lt;math&amp;gt;[CF_i,child_i]&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i=1,2,...,B&amp;lt;/math&amp;gt;, &#039;&#039;child&#039;&#039; - указатель на i-й дочерний узел, &amp;lt;math&amp;gt;CF_i&amp;lt;/math&amp;gt; - CF вектор соответствующего подкластера.&lt;br /&gt;
&lt;br /&gt;
Каждый листьевой узел имеет ссылку на два соседних узла (&#039;&#039;prev&#039;&#039; и &#039;&#039;next&#039;&#039;) для того, чтобы связать все узлы для эффективного сканирования.&lt;br /&gt;
Все листьевые узлы должны удовлетворять пороговому ограничению &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, т.е. диаметр (радиус) не должен превосходить &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;.&lt;br /&gt;
В процессе вставки новых данных CF дерево строится динамически. Оно использует вставку данных для кластеризации точно также как &amp;lt;math&amp;gt;B+&amp;lt;/math&amp;gt; [https://ru.wikipedia.org/wiki/B%2B-%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE дерево] использует её для поиска.&lt;br /&gt;
CF дерево очень компактно, поскольку каждый листьевой узел - это не просто точка, а подкластер (который объединяет множество точек с учётом ограничения &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Операция вставки в &#039;&#039;&#039;CF&#039;&#039;&#039; дерево ====&lt;br /&gt;
&lt;br /&gt;
Опишем алгоритм вставки элемнта &amp;lt;math&amp;gt;Ent&amp;lt;/math&amp;gt; в CF дерево:&lt;br /&gt;
&lt;br /&gt;
1) &#039;&#039;Определение подходящего листа&#039;&#039;: Начиная с корня, алгоритм рекурсивно спускается по CF дереву, выбирая &#039;&#039;&#039;ближайший&#039;&#039;&#039; дочерний узел в соответствии с выбранной метрикой &amp;lt;math&amp;gt;D0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D4&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &#039;&#039;Преобразование листа&#039;&#039;: Когда алгоритм доходит до листа, он находит ближайшую листьевой элемент, скажем, &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;, а затем проверяет, можно ли добавить &#039;&#039;Ent&#039;&#039; к &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt; без нарушения порогового условия. Если да, то с учётом этого изменяется CF вектор для &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;; если нет, то &#039;&#039;Ent&#039;&#039; становится новым элементом листа. Если в листе для этого достаточно места, то шаг окончен, иначе он должен &amp;quot;расщепиться&amp;quot;. Расщепление узла производится при помощи выбора за основу наиболее удалённой друг от друга пары элементов и перераспределение оставшихся элементов в соответствии с выбранным критерием близости.&lt;br /&gt;
&lt;br /&gt;
3) &#039;&#039;Преобразование пути к листу&#039;&#039;: После вставки &#039;&#039;Ent&#039;&#039; в лист мы должны обновить информацию о CF для каждого нелистьевого элемента на пути к листу. При отсутствии расщепления это означает простое сложение CF векторов для отражения факта добавления &#039;&#039;Ent&#039;&#039;. Расщепление листа же требует вставки нового нелистьевого элемента в родительский узел для задания только что созданного листа. Если у родителя есть место для этого элемента, то необходимо просто преобразовать CF векторы на всех более высоких уровнях. В общем случае, однако, нам также придётся расщепить родительский узел, и так далее до корня. Если расщеплён корень, то высота дерева увеличивается на единицу.&lt;br /&gt;
&lt;br /&gt;
4) &#039;&#039;Улучшение слияния&#039;&#039;: Расщепление вызвано ограничением на размер узла, который не зависит от кластеризационных свойств данных. Если во входящем потоке присутствуют &amp;quot;искажённые&amp;quot; (из областей с низкой плотностью) данные, это может повлиять на качество кластеризации, а также уменьшить эффективность использования памяти. Дополнительный шаг алгоритма помогает решить эти проблемы: предположим, что произошло расщепление листа, и распространение этого процесса остановилось на некотором нелистьевом узле &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt;, то есть &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; может вместить дополнительный элемент, полученный после расщепления. Теперь мы сканируем узел &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; для нахождения двух наиболее близких элементов. Если это не пара, отвечающая расщеплению, мы пытаемся объединить их и поставить в соответствие два дочерних узла. Если количество элементов в дочерних узлах  больше B, мы снова расщепляем результат объединения.&lt;br /&gt;
В процессе повторного расщепления, в случае, если один источник собирает достаточно элементов для того, чтобы полностью заполнить узел, оставшиеся элементы передаются другом источнику. В итоге, если объединённые элементы помещаются в одном узле, в нём освобождается место для ещё одного элемента. Тем самым увеличивается степень использования свободного пространства и откладывается дальнейшее расщепление. В ином случае мы улучшаем распределение элементов в двух ближайших подкластерах.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро алгоритма заключается в многократном выполнении операции вставки нового элемента в дерево, в процессе чего требуется вычисление следующих величин:&lt;br /&gt;
&lt;br /&gt;
* радиуса &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; или диаметра &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластерного элемента. Выполняется при попытке вставить новый элемент в один из подкластеров листьевого узла дерева.&lt;br /&gt;
&lt;br /&gt;
* расстояния между двумя элементами. Выполняется при поиске ближайшего по отношению к новому элементу подкластера в узле дерева по одной из рассмотренных в разд. 1.2.1 метрик &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Зная характеристики кластерных элементов &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;, в результате алгебраических преобразований можно получить следующие упрощенные формулы вычисления необходимых значений:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\vec{X_0} = \frac{\vec{LS}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{SS - 2\vec{X_0}\vec{LS} + N(\vec{X_0})^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{2(N*SS - (\vec{LS})^2)}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{N_1*SS_2 + N_2*SS_1 - 2\vec{LS_1}\vec{LS_2}}{N_1*N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{2((N_1+N_2)(SS_1+SS_2)-(\vec{LS_1}+\vec{LS_2})^2)}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Реализация алгоритма BIRCH состояит из следующих четырёх фаз:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 1&#039;&#039;&#039;. Главной задачей фазы 1 является сканирование всех данных и построение в памяти исходного CF дерева, используя заданное количество памяти. Это дерево стремится отразить информацию о кластеризации данных настолько хорошо, насколько это позволяют ограничения по памяти. При этом плотно распределённые данные группируются в подкластеры, а более разрозненные данные удаляются. После завершения фазы 1 вспомогательные вычисления в дальнейших фазах будут:&lt;br /&gt;
&lt;br /&gt;
1) быстрее, потому что (а) больше не нужны операции ввода-вывода, (b) проблема кластеризации начальных данных упрощается до проблемы кластеризации подкластеров в листьях;&lt;br /&gt;
&lt;br /&gt;
2) точнее, потому что (а) большинство данных с низкой плотностью удалены, (b) оставшиеся данные распределены оптимально (в соответствии с доступным количеством памяти);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 2&#039;&#039;&#039;. Данная фаза является опциональной. Известно, что существующие методы глобальной кластеризации, используемые в рамках фазы 3, имеют различные диапазоны входных значений, при которых их реализация наиболее эффективна. Поэтому потенциально существует пробел между размером фазы 1 и входными значениями фазы 3. И фаза 2 как раз является недостающим связующим звеном: так же как и фаза 1, она сканирует листьевые элементы начального CF дерева для того, чтобы построить меньшее дерево, удаляя ещё больше элементов с низкой плотностью и группируя переполненные подкластеры в большие кластеры.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 3&#039;&#039;&#039;. В данной фазе для листьевых элементов применяется (любой подходящий) алгоритм глобальной кластеризации. Существующие алгоритмы кластеризации наборов точек могут также работать с наборами подкластеров, каждый из которых представлен своим CF вектором. Зная CF вектор, можно вычислить центроид и в дальнейшем заменить всю информацию о кластере этим значением (этого достаточно для вычисления большинства необходимых метрик). После фазы 3 мы получаем набор кластеров, который отражает основные характеристики распределяемых данных.&lt;br /&gt;
Однако, всё ещё могут оставаться некоторые неточности, для устранения которых существует фаза 4.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 4&#039;&#039;&#039;. Данная фаза является опциональной и влечёт за собой затраты на дополнительное сканирование данных для корректировки неточностей и дальнейшего улучшения кластеризации. Фаза 4 использует центроиды кластеров, полученные в фазе 3 для как основы и перераспределяет точки входных данных в ближайшие для них основы для получения нового списка кластеров. Фаза 4, если это необходимо пользователю, может быть расширена дополнительными проходами для уверенности в том, что результат приближается к оптимальному.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Для начала проанализируем вычислительную сложность фазы 1.&lt;br /&gt;
Максимальный размер дерева &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt;. Для того чтобы вставить элемент, мы должны пройти путь от корня до листа (это около &amp;lt;math&amp;gt;1+log_B\frac{M}{P}&amp;lt;/math&amp;gt; узлов). В каждом узле в поисках &amp;quot;ближайшего&amp;quot; нам необходимо просмотреть B элементов; сложность для каждого элемента пропорциональна размерности &#039;&#039;d&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Поэтому сложность вставки всех входных точек &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В случае, когда необходимо перестроить дерево, предположим, что ES - это размер CF элемента. Существует максимум &amp;lt;math&amp;gt;\frac{M}{ES}&amp;lt;/math&amp;gt; листьевых элементов для вставки, поэтому сложность повторной вставки листьевых элементов &amp;lt;math&amp;gt;O(d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Количество итераций перестройки дерева зависит от пороговой величины. На самом деле, это около &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; (двоичное основание появилось из-за того, что мы не можем провести оценку более чем в 2 раза отличающуюся от текущего размера). &amp;lt;math&amp;gt;N_0&amp;lt;/math&amp;gt; - это число входных точек, загруженных в память с пороговым ограничением &amp;lt;math&amp;gt;T_0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Соответственно, итоговая сложность фазы 1 &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P})+log_2\frac{N}{N_0}*d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Анализ фазы 2 проводится аналогично.&lt;br /&gt;
&lt;br /&gt;
Что касается операций ввода-вывода, то в фазе 1 данные сканируются один раз, а в фазе 2 не сканируются вовсе.&lt;br /&gt;
Некоторое количество вычислений связано с удалением точек из областей с низкой плотностью.&lt;br /&gt;
Если количество доступной для этой операции памяти не больше &#039;&#039;M&#039;&#039; и проведено порядка &amp;lt;math&amp;gt;log_2{N}{N_0}&amp;lt;/math&amp;gt; перестроек дерева, то сложность ввода-вывода для фазы 1 не отличается существенно от сложности чтения из файла. Основываясь рассуждениях выше, сложность фаз 1 и 2 будет линейно увеличиваться с ростом N.&lt;br /&gt;
&lt;br /&gt;
В фазе 3 нет операций ввода-вывода. Сложность фазы 3 ограничена константой, которая зависит от максимального размера входных данных и варианта выбранного алгоритма для кластеризации. &lt;br /&gt;
&lt;br /&gt;
Фаза 4 снова сканирует данные и зписывает каждую точку в подходящий кластер; время работы пропорционально &amp;lt;math&amp;gt;N*K&amp;lt;/math&amp;gt;.   &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Достоинства алгоритма ===&lt;br /&gt;
По сравнению с предыдущими методами BIRCH обладает следующими достоинствами:&lt;br /&gt;
&lt;br /&gt;
1. BIRCH является локальным алгоритмом, то есть каждое решение о каждом элементе кластера принимается без повторного сканирования данных или уже существующих кластеров. Используются только метрики, отражающие близость элементов друг к другу.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH использует факт неравномерного распределения данных в пространстве и поэтому не все данные рассматриваются как одинаково важные для построения кластера. Области с большой плотностью обрабатываются как единый кластер. Данные в более разреженных областях могут удаляться (опционально).&lt;br /&gt;
&lt;br /&gt;
3. BIRCH использует всю доступную память для получения наилучших из возможных подкластеров, в то же время минимизируя затраты на операции ввода/вывода. Оптимизация процесса кластеризации достигается за счет использования взвешенно-сбалансированного дерева. При этом время исполнения линейно.&lt;br /&gt;
&lt;br /&gt;
4. BIRCH не требует всего набора данных заранее (при этом просматривает его всего один раз).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&lt;br /&gt;
[1] Википедия&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;/div&gt;</summary>
		<author><name>Светлана Морозова</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13493</id>
		<title>Участник:Smirnov.maxim/BIRCH</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13493"/>
		<updated>2016-10-23T09:30:15Z</updated>

		<summary type="html">&lt;p&gt;Светлана Морозова: /* Последовательная сложность алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Нахождение полезных для анализа закономерностей в больших объёмах данных с недавних пор вызывает значительный интерес. В связи с этим ввелось и стало активно развиваться такое понятие как &#039;&#039;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7 кластеризация]&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Ранние работы и алгоритмы, разработанные в этой области, не уделяли достаточного внимания анализу очень больших наборов данных или минимизации издержек на процессы ввода-вывода.&lt;br /&gt;
Решением этих проблем стал алгоритм, известный как BIRCH.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIRCH&#039;&#039;&#039; (balanced iterative reducing and clustering using hierarchies)- алгоритм, применяемый в области [https://ru.wikipedia.org/wiki/Data_mining Data mining] и использующий принципы [https://ru.wikipedia.org/wiki/%D0%98%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F иерархической кластеризации].&lt;br /&gt;
&lt;br /&gt;
Если имеется очень большой набор данных, то в пространстве он распределен, как правило, неравномерно. Кластерный анализ определяет места наибольшего и наименьшего скоплений, чтобы таким образом понять всю картину целиком. Кроме того, полученные кластеры визуализируются гораздо нагляднее, чем начальные &amp;quot;сырые&amp;quot; данные.&lt;br /&gt;
Задачей алгоритмов кластеризации является не только простое разбиение данных на кластеры, но и работа в рамках ограниченного объёма доступной памяти (как правило, её объём гораздо меньше, чем размер исходного набора данных) и минимизация времени, требуемого на операции ввода-вывода.&lt;br /&gt;
&lt;br /&gt;
Для наилучшего решения этих проблем BIRCH распределяет входящие данные по кластерам динамически. Для эффективной кластеризации алгоритму требуется всего одно сканирование данных (т.е. с увеличением количества данных сложность увеличивается линейно). А при помощи одной (или более) дополнительных итераций можно и далее улучшать эффективность. BIRCH также является первым алгоритмом, предложенным для эффективного управления &amp;quot;шумами&amp;quot; (данными, которые не вписываются в общее представление модели).&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Теоретическая основа ===&lt;br /&gt;
&lt;br /&gt;
Пусть в кластере имеются &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}, i=1,2,...,N&amp;lt;/math&amp;gt;.&lt;br /&gt;
Тогда &#039;&#039;&#039;центроид&#039;&#039;&#039; &amp;lt;math&amp;gt;{\vec{{X_0}}}&amp;lt;/math&amp;gt;, &#039;&#039;&#039;радиус&#039;&#039;&#039; &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &#039;&#039;&#039;диаметр&#039;&#039;&#039; &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластера определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;{\vec{X_0}}=\frac{\sum_{i=1}^N\vec{X_i}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{\sum_{i=1}^N{(\vec{X_i} - \vec{X_0})}^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{\sum_{i=1}^N\sum_{j=1}^N{(\vec{X_i} - \vec{X_j})}^2}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; - это среднее расстояние от каждой точки до центроида. &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; - это среднее расстояние между парами в кластере. Данные величины являются альтернативными метриками плотности кластера относительно центроида.&lt;br /&gt;
&lt;br /&gt;
Для измерения близости друг к другу двух кластеров вводятся следующие метрики:&lt;br /&gt;
&lt;br /&gt;
пусть даны центроиды двух кластеров &amp;lt;math&amp;gt;\vec{X_{01}}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\vec{X_{02}}&amp;lt;/math&amp;gt;.&lt;br /&gt;
Евклидова метрика &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt; и метрика Манхэттена &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt; между двумя кластерами определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_0 = ((\vec{X_{01}}-\vec{X_{02}})^2)^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_1 = |\vec{X_{01}}-\vec{X_{02}}| = \sum_{i=1}^d |{\vec{X_{01}}}^{(i)}-{\vec{X_{02}}}^{(i)}| &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть имеются два кластера, содержащих соответственно  &amp;lt;math&amp;gt;N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;N_2&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i= 1,2, ...,N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\{\vec{X_j}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j= N_1+1,N_1+2, ...,N_1+N_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Среднее расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &#039;&#039;&#039;среднее внутрикластерное расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &#039;&#039;&#039;дисперсия&#039;&#039;&#039; &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; для двух кластеров определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{\sum_{i=1}^{N_1}\sum_{j=N_1+1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{N_1N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{\sum_{i=1}^{N_1+N_2}\sum_{j=1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_4 = \sum_{k=1}^{N_1+N_2}(\vec{X_k} - \frac{\sum_{i=1}^{N_1+N_2}\vec{X_i}}{N_1+N_2})^2 - \sum_{i=1}^{N_1}(\vec{X_i} - \frac{\sum_{i=1}^{N_1}\vec{X_i}}{N_1})^2 - \sum_{j=N_1+1}^{N_1+N_2}(\vec{X_j} - \frac{\sum_{i=N_1+1}^{N_1+N_2}\vec{X_i}}{N_2})^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Таким образом, величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; относятся к отдельным кластерам, а &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; - к объединению двух кластеров.&lt;br /&gt;
&lt;br /&gt;
=== Кластерный элемент и кластерное дерево ===&lt;br /&gt;
&lt;br /&gt;
В основе концепции алгоритма BIRCH лежат понятия &#039;&#039;&#039;кластерного элемента&#039;&#039;&#039; и &#039;&#039;&#039;кластерного дерева (CF Tree)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====Кластерный элемент ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; Пусть в кластере содержатся  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности  &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;:&amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;i=1,2,...,N&amp;lt;/math&amp;gt;. &lt;br /&gt;
&#039;&#039;&#039;Кластерный элемент (CF)&#039;&#039;&#039; - тройка чисел, характеризующая информацию о кластере: &lt;br /&gt;
&amp;lt;math&amp;gt;CF = (N, \vec{LS}, SS)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - количество элементов входных данных, содержащихся в кластере, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; - линейная сумма входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}\vec{X_i}&amp;lt;/math&amp;gt;), &amp;lt;math&amp;gt;SS&amp;lt;/math&amp;gt; - сумма квадратов входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}{\vec{X_i}}^2&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Теорема&#039;&#039;&#039; Пусть &amp;lt;math&amp;gt;CF_1 = (N_1, \vec{LS_1}, SS_1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;CF_2 = (N_1, \vec{LS_2}, SS_2)&amp;lt;/math&amp;gt; - CF векторы двух непересекающихся кластеров. Тогда при их объединении образуется кластер со следующим CF вектором: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF = CF_1 + CF_2 = (N_1+N_2, \vec{LS_1}+\vec{LS_2}, SS_1+SS_2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Из указанных выше определения и теоремы вытекает тот факт, что при объединении кластеров их CF вектор может вычисляться инкрементно и точно. &lt;br /&gt;
Легко показать, что вычислить величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;, как и обычные метрики, также не составит труда.&lt;br /&gt;
&lt;br /&gt;
Таким образом, в данном случае информацией о кластере является не весь набор точек, а вектор CF. Хранение одного только вектора может показаться неэффективным, но этого вполне достаточно для оперирования всеми необходимыми метриками, на основе которых принимаются решения в алгоритме BIRCH.&lt;br /&gt;
&lt;br /&gt;
==== Кластерное дерево ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; &#039;&#039;&#039;Кластерное дерево (CF Tree)&#039;&#039;&#039; - это взвешенно сбалансированное дерево с двумя параметрами: &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - коэффициент разветвления, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - пороговая величина. Каждый нелистьевой узел дерева имеет не более чем &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; вхождений узлов следующей формы: &amp;lt;math&amp;gt;[CF_i,child_i]&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i=1,2,...,B&amp;lt;/math&amp;gt;, &#039;&#039;child&#039;&#039; - указатель на i-й дочерний узел, &amp;lt;math&amp;gt;CF_i&amp;lt;/math&amp;gt; - CF вектор соответствующего подкластера.&lt;br /&gt;
&lt;br /&gt;
Каждый листьевой узел имеет ссылку на два соседних узла (&#039;&#039;prev&#039;&#039; и &#039;&#039;next&#039;&#039;) для того, чтобы связать все узлы для эффективного сканирования.&lt;br /&gt;
Все листьевые узлы должны удовлетворять пороговому ограничению &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, т.е. диаметр (радиус) не должен превосходить &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;.&lt;br /&gt;
В процессе вставки новых данных CF дерево строится динамически. Оно использует вставку данных для кластеризации точно также как &amp;lt;math&amp;gt;B+&amp;lt;/math&amp;gt; [https://ru.wikipedia.org/wiki/B%2B-%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE дерево] использует её для поиска.&lt;br /&gt;
CF дерево очень компактно, поскольку каждый листьевой узел - это не просто точка, а подкластер (который объединяет множество точек с учётом ограничения &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Операция вставки в &#039;&#039;&#039;CF&#039;&#039;&#039; дерево ====&lt;br /&gt;
&lt;br /&gt;
Опишем алгоритм вставки элемнта &amp;lt;math&amp;gt;Ent&amp;lt;/math&amp;gt; в CF дерево:&lt;br /&gt;
&lt;br /&gt;
1) &#039;&#039;Определение подходящего листа&#039;&#039;: Начиная с корня, алгоритм рекурсивно спускается по CF дереву, выбирая &#039;&#039;&#039;ближайший&#039;&#039;&#039; дочерний узел в соответствии с выбранной метрикой &amp;lt;math&amp;gt;D0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D4&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &#039;&#039;Преобразование листа&#039;&#039;: Когда алгоритм доходит до листа, он находит ближайшую листьевой элемент, скажем, &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;, а затем проверяет, можно ли добавить &#039;&#039;Ent&#039;&#039; к &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt; без нарушения порогового условия. Если да, то с учётом этого изменяется CF вектор для &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;; если нет, то &#039;&#039;Ent&#039;&#039; становится новым элементом листа. Если в листе для этого достаточно места, то шаг окончен, иначе он должен &amp;quot;расщепиться&amp;quot;. Расщепление узла производится при помощи выбора за основу наиболее удалённой друг от друга пары элементов и перераспределение оставшихся элементов в соответствии с выбранным критерием близости.&lt;br /&gt;
&lt;br /&gt;
3) &#039;&#039;Преобразование пути к листу&#039;&#039;: После вставки &#039;&#039;Ent&#039;&#039; в лист мы должны обновить информацию о CF для каждого нелистьевого элемента на пути к листу. При отсутствии расщепления это означает простое сложение CF векторов для отражения факта добавления &#039;&#039;Ent&#039;&#039;. Расщепление листа же требует вставки нового нелистьевого элемента в родительский узел для задания только что созданного листа. Если у родителя есть место для этого элемента, то необходимо просто преобразовать CF векторы на всех более высоких уровнях. В общем случае, однако, нам также придётся расщепить родительский узел, и так далее до корня. Если расщеплён корень, то высота дерева увеличивается на единицу.&lt;br /&gt;
&lt;br /&gt;
4) &#039;&#039;Улучшение слияния&#039;&#039;: Расщепление вызвано ограничением на размер узла, который не зависит от кластеризационных свойств данных. Если во входящем потоке присутствуют &amp;quot;искажённые&amp;quot; (из областей с низкой плотностью) данные, это может повлиять на качество кластеризации, а также уменьшить эффективность использования памяти. Дополнительный шаг алгоритма помогает решить эти проблемы: предположим, что произошло расщепление листа, и распространение этого процесса остановилось на некотором нелистьевом узле &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt;, то есть &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; может вместить дополнительный элемент, полученный после расщепления. Теперь мы сканируем узел &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; для нахождения двух наиболее близких элементов. Если это не пара, отвечающая расщеплению, мы пытаемся объединить их и поставить в соответствие два дочерних узла. Если количество элементов в дочерних узлах  больше B, мы снова расщепляем результат объединения.&lt;br /&gt;
В процессе повторного расщепления, в случае, если один источник собирает достаточно элементов для того, чтобы полностью заполнить узел, оставшиеся элементы передаются другом источнику. В итоге, если объединённые элементы помещаются в одном узле, в нём освобождается место для ещё одного элемента. Тем самым увеличивается степень использования свободного пространства и откладывается дальнейшее расщепление. В ином случае мы улучшаем распределение элементов в двух ближайших подкластерах.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро алгоритма заключается в многократном выполнении операции вставки нового элемента в дерево, в процессе чего требуется вычисление следующих величин:&lt;br /&gt;
&lt;br /&gt;
* радиуса &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; или диаметра &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластерного элемента. Выполняется при попытке вставить новый элемент в один из подкластеров листьевого узла дерева.&lt;br /&gt;
&lt;br /&gt;
* расстояния между двумя элементами. Выполняется при поиске ближайшего по отношению к новому элементу подкластера в узле дерева по одной из рассмотренных в разд. 1.2.1 метрик &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Зная характеристики кластерных элементов &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;, в результате алгебраических преобразований можно получить следующие упрощенные формулы вычисления необходимых значений:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\vec{X_0} = \frac{\vec{LS}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{SS - 2\vec{X_0}\vec{LS} + N(\vec{X_0})^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{2(N*SS - (\vec{LS})^2)}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{N_1*SS_2 + N_2*SS_1 - 2\vec{LS_1}\vec{LS_2}}{N_1*N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{2((N_1+N_2)(SS_1+SS_2)-(\vec{LS_1}+\vec{LS_2})^2)}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Реализация алгоритма BIRCH состояит из следующих четырёх фаз:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 1&#039;&#039;&#039;. Главной задачей фазы 1 является сканирование всех данных и построение в памяти исходного CF дерева, используя заданное количество памяти. Это дерево стремится отразить информацию о кластеризации данных настолько хорошо, насколько это позволяют ограничения по памяти. При этом плотно распределённые данные группируются в подкластеры, а более разрозненные данные удаляются. После завершения фазы 1 вспомогательные вычисления в дальнейших фазах будут:&lt;br /&gt;
&lt;br /&gt;
1) быстрее, потому что (а) больше не нужны операции ввода-вывода, (b) проблема кластеризации начальных данных упрощается до проблемы кластеризации подкластеров в листьях;&lt;br /&gt;
&lt;br /&gt;
2) точнее, потому что (а) большинство данных с низкой плотностью удалены, (b) оставшиеся данные распределены оптимально (в соответствии с доступным количеством памяти);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 2&#039;&#039;&#039;. Данная фаза является опциональной. Известно, что существующие методы глобальной кластеризации, используемые в рамках фазы 3, имеют различные диапазоны входных значений, при которых их реализация наиболее эффективна. Поэтому потенциально существует пробел между размером фазы 1 и входными значениями фазы 3. И фаза 2 как раз является недостающим связующим звеном: так же как и фаза 1, она сканирует листьевые элементы начального CF дерева для того, чтобы построить меньшее дерево, удаляя ещё больше элементов с низкой плотностью и группируя переполненные подкластеры в большие кластеры.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 3&#039;&#039;&#039;. В данной фазе для листьевых элементов применяется (любой подходящий) алгоритм глобальной кластеризации. Существующие алгоритмы кластеризации наборов точек могут также работать с наборами подкластеров, каждый из которых представлен своим CF вектором. Зная CF вектор, можно вычислить центроид и в дальнейшем заменить всю информацию о кластере этим значением (этого достаточно для вычисления большинства необходимых метрик). После фазы 3 мы получаем набор кластеров, который отражает основные характеристики распределяемых данных.&lt;br /&gt;
Однако, всё ещё могут оставаться некоторые неточности, для устранения которых существует фаза 4.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 4&#039;&#039;&#039;. Данная фаза является опциональной и влечёт за собой затраты на дополнительное сканирование данных для корректировки неточностей и дальнейшего улучшения кластеризации. Фаза 4 использует центроиды кластеров, полученные в фазе 3 для как основы и перераспределяет точки входных данных в ближайшие для них основы для получения нового списка кластеров. Фаза 4, если это необходимо пользователю, может быть расширена дополнительными проходами для уверенности в том, что результат приближается к оптимальному.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Для начала проанализируем вычислительную сложность фазы 1.&lt;br /&gt;
Максимальный размер дерева &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt;. Для того чтобы вставить элемент, мы должны пройти путь от корня до листа (это около &amp;lt;math&amp;gt;1+log_B\frac{M}{P}&amp;lt;/math&amp;gt; узлов). В каждом узле в поисках &amp;quot;ближайшего&amp;quot; нам необходимо просмотреть B элементов; сложность для каждого элемента пропорциональна размерности &#039;&#039;d&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Поэтому сложность вставки всех входных точек &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В случае, когда необходимо перестроить дерево, предположим, что ES - это размер CF элемента. Существует максимум &amp;lt;math&amp;gt;\frac{M}{ES}&amp;lt;/math&amp;gt; листьевых элементов для вставки, поэтому сложность повторной вставки листьевых элементов &amp;lt;math&amp;gt;O(d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Количество итераций перестройки дерева зависит от пороговой величины. На самом деле, это около &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; (двоичное основание появилось из-за того, что мы никогда не можем провести оценку более чем в 2 раза отличающуюся от текущего размера. &amp;lt;math&amp;gt;N_0&amp;lt;/math&amp;gt; - это число входных точек, загруженных в память с пороговым ограничением &amp;lt;math&amp;gt;T_0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Соответственно, итоговая сложность фазы 1 &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P})+log_2\frac{N}{N_0}*d*\frac{M}{ES}*B(1+log_B{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Анализ фазы 2 проводится аналогично.&lt;br /&gt;
&lt;br /&gt;
Что касается операций ввода-вывода, то в фазе 1 данные сканируются один раз, а в фазе 2 не сканируются вовсе.&lt;br /&gt;
Некоторое количество вычислений связано с удалением точек из областей с низкой плотностью.&lt;br /&gt;
Если количество доступной для этой операции памяти не больше &#039;&#039;M&#039;&#039; и проведено порядка &amp;lt;math&amp;gt;log_2{N}{N_0}&amp;lt;/math&amp;gt; перестроек дерева, то сложность ввода-вывода для фазы 1 не отличается существенно от сложности чтения из файла. Основываясь рассуждениях выше, сложность фаз 1 и 2 будет линейно увеличиваться с ростом N.&lt;br /&gt;
&lt;br /&gt;
В фазе 3 нет операций ввода-вывода. Сложность фазы 3 ограничена константой, которая зависит от максимального размера входных данных и варианта выбранного алгоритма для кластеризации. &lt;br /&gt;
&lt;br /&gt;
Фаза 4 снова сканирует данные и зписывает каждую точку в подходящий кластер; время работы пропорционально &amp;lt;math&amp;gt;N*K&amp;lt;/math&amp;gt;.   &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Достоинства алгоритма ===&lt;br /&gt;
По сравнению с предыдущими методами BIRCH обладает следующими достоинствами:&lt;br /&gt;
&lt;br /&gt;
1. BIRCH является локальным алгоритмом, то есть каждое решение о каждом элементе кластера принимается без повторного сканирования данных или уже существующих кластеров. Используются только метрики, отражающие близость элементов друг к другу.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH использует факт неравномерного распределения данных в пространстве и поэтому не все данные рассматриваются как одинаково важные для построения кластера. Области с большой плотностью обрабатываются как единый кластер. Данные в более разреженных областях могут удаляться (опционально).&lt;br /&gt;
&lt;br /&gt;
3. BIRCH использует всю доступную память для получения наилучших из возможных подкластеров, в то же время минимизируя затраты на операции ввода/вывода. Оптимизация процесса кластеризации достигается за счет использования взвешенно-сбалансированного дерева. При этом время исполнения линейно.&lt;br /&gt;
&lt;br /&gt;
4. BIRCH не требует всего набора данных заранее (при этом просматривает его всего один раз).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&lt;br /&gt;
[1] Википедия&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;/div&gt;</summary>
		<author><name>Светлана Морозова</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13492</id>
		<title>Участник:Smirnov.maxim/BIRCH</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13492"/>
		<updated>2016-10-23T09:29:18Z</updated>

		<summary type="html">&lt;p&gt;Светлана Морозова: /* Последовательная сложность алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Нахождение полезных для анализа закономерностей в больших объёмах данных с недавних пор вызывает значительный интерес. В связи с этим ввелось и стало активно развиваться такое понятие как &#039;&#039;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7 кластеризация]&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Ранние работы и алгоритмы, разработанные в этой области, не уделяли достаточного внимания анализу очень больших наборов данных или минимизации издержек на процессы ввода-вывода.&lt;br /&gt;
Решением этих проблем стал алгоритм, известный как BIRCH.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIRCH&#039;&#039;&#039; (balanced iterative reducing and clustering using hierarchies)- алгоритм, применяемый в области [https://ru.wikipedia.org/wiki/Data_mining Data mining] и использующий принципы [https://ru.wikipedia.org/wiki/%D0%98%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F иерархической кластеризации].&lt;br /&gt;
&lt;br /&gt;
Если имеется очень большой набор данных, то в пространстве он распределен, как правило, неравномерно. Кластерный анализ определяет места наибольшего и наименьшего скоплений, чтобы таким образом понять всю картину целиком. Кроме того, полученные кластеры визуализируются гораздо нагляднее, чем начальные &amp;quot;сырые&amp;quot; данные.&lt;br /&gt;
Задачей алгоритмов кластеризации является не только простое разбиение данных на кластеры, но и работа в рамках ограниченного объёма доступной памяти (как правило, её объём гораздо меньше, чем размер исходного набора данных) и минимизация времени, требуемого на операции ввода-вывода.&lt;br /&gt;
&lt;br /&gt;
Для наилучшего решения этих проблем BIRCH распределяет входящие данные по кластерам динамически. Для эффективной кластеризации алгоритму требуется всего одно сканирование данных (т.е. с увеличением количества данных сложность увеличивается линейно). А при помощи одной (или более) дополнительных итераций можно и далее улучшать эффективность. BIRCH также является первым алгоритмом, предложенным для эффективного управления &amp;quot;шумами&amp;quot; (данными, которые не вписываются в общее представление модели).&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Теоретическая основа ===&lt;br /&gt;
&lt;br /&gt;
Пусть в кластере имеются &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}, i=1,2,...,N&amp;lt;/math&amp;gt;.&lt;br /&gt;
Тогда &#039;&#039;&#039;центроид&#039;&#039;&#039; &amp;lt;math&amp;gt;{\vec{{X_0}}}&amp;lt;/math&amp;gt;, &#039;&#039;&#039;радиус&#039;&#039;&#039; &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &#039;&#039;&#039;диаметр&#039;&#039;&#039; &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластера определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;{\vec{X_0}}=\frac{\sum_{i=1}^N\vec{X_i}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{\sum_{i=1}^N{(\vec{X_i} - \vec{X_0})}^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{\sum_{i=1}^N\sum_{j=1}^N{(\vec{X_i} - \vec{X_j})}^2}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; - это среднее расстояние от каждой точки до центроида. &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; - это среднее расстояние между парами в кластере. Данные величины являются альтернативными метриками плотности кластера относительно центроида.&lt;br /&gt;
&lt;br /&gt;
Для измерения близости друг к другу двух кластеров вводятся следующие метрики:&lt;br /&gt;
&lt;br /&gt;
пусть даны центроиды двух кластеров &amp;lt;math&amp;gt;\vec{X_{01}}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\vec{X_{02}}&amp;lt;/math&amp;gt;.&lt;br /&gt;
Евклидова метрика &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt; и метрика Манхэттена &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt; между двумя кластерами определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_0 = ((\vec{X_{01}}-\vec{X_{02}})^2)^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_1 = |\vec{X_{01}}-\vec{X_{02}}| = \sum_{i=1}^d |{\vec{X_{01}}}^{(i)}-{\vec{X_{02}}}^{(i)}| &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть имеются два кластера, содержащих соответственно  &amp;lt;math&amp;gt;N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;N_2&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i= 1,2, ...,N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\{\vec{X_j}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j= N_1+1,N_1+2, ...,N_1+N_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Среднее расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &#039;&#039;&#039;среднее внутрикластерное расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &#039;&#039;&#039;дисперсия&#039;&#039;&#039; &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; для двух кластеров определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{\sum_{i=1}^{N_1}\sum_{j=N_1+1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{N_1N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{\sum_{i=1}^{N_1+N_2}\sum_{j=1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_4 = \sum_{k=1}^{N_1+N_2}(\vec{X_k} - \frac{\sum_{i=1}^{N_1+N_2}\vec{X_i}}{N_1+N_2})^2 - \sum_{i=1}^{N_1}(\vec{X_i} - \frac{\sum_{i=1}^{N_1}\vec{X_i}}{N_1})^2 - \sum_{j=N_1+1}^{N_1+N_2}(\vec{X_j} - \frac{\sum_{i=N_1+1}^{N_1+N_2}\vec{X_i}}{N_2})^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Таким образом, величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; относятся к отдельным кластерам, а &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; - к объединению двух кластеров.&lt;br /&gt;
&lt;br /&gt;
=== Кластерный элемент и кластерное дерево ===&lt;br /&gt;
&lt;br /&gt;
В основе концепции алгоритма BIRCH лежат понятия &#039;&#039;&#039;кластерного элемента&#039;&#039;&#039; и &#039;&#039;&#039;кластерного дерева (CF Tree)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====Кластерный элемент ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; Пусть в кластере содержатся  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности  &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;:&amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;i=1,2,...,N&amp;lt;/math&amp;gt;. &lt;br /&gt;
&#039;&#039;&#039;Кластерный элемент (CF)&#039;&#039;&#039; - тройка чисел, характеризующая информацию о кластере: &lt;br /&gt;
&amp;lt;math&amp;gt;CF = (N, \vec{LS}, SS)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - количество элементов входных данных, содержащихся в кластере, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; - линейная сумма входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}\vec{X_i}&amp;lt;/math&amp;gt;), &amp;lt;math&amp;gt;SS&amp;lt;/math&amp;gt; - сумма квадратов входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}{\vec{X_i}}^2&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Теорема&#039;&#039;&#039; Пусть &amp;lt;math&amp;gt;CF_1 = (N_1, \vec{LS_1}, SS_1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;CF_2 = (N_1, \vec{LS_2}, SS_2)&amp;lt;/math&amp;gt; - CF векторы двух непересекающихся кластеров. Тогда при их объединении образуется кластер со следующим CF вектором: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF = CF_1 + CF_2 = (N_1+N_2, \vec{LS_1}+\vec{LS_2}, SS_1+SS_2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Из указанных выше определения и теоремы вытекает тот факт, что при объединении кластеров их CF вектор может вычисляться инкрементно и точно. &lt;br /&gt;
Легко показать, что вычислить величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;, как и обычные метрики, также не составит труда.&lt;br /&gt;
&lt;br /&gt;
Таким образом, в данном случае информацией о кластере является не весь набор точек, а вектор CF. Хранение одного только вектора может показаться неэффективным, но этого вполне достаточно для оперирования всеми необходимыми метриками, на основе которых принимаются решения в алгоритме BIRCH.&lt;br /&gt;
&lt;br /&gt;
==== Кластерное дерево ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; &#039;&#039;&#039;Кластерное дерево (CF Tree)&#039;&#039;&#039; - это взвешенно сбалансированное дерево с двумя параметрами: &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - коэффициент разветвления, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - пороговая величина. Каждый нелистьевой узел дерева имеет не более чем &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; вхождений узлов следующей формы: &amp;lt;math&amp;gt;[CF_i,child_i]&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i=1,2,...,B&amp;lt;/math&amp;gt;, &#039;&#039;child&#039;&#039; - указатель на i-й дочерний узел, &amp;lt;math&amp;gt;CF_i&amp;lt;/math&amp;gt; - CF вектор соответствующего подкластера.&lt;br /&gt;
&lt;br /&gt;
Каждый листьевой узел имеет ссылку на два соседних узла (&#039;&#039;prev&#039;&#039; и &#039;&#039;next&#039;&#039;) для того, чтобы связать все узлы для эффективного сканирования.&lt;br /&gt;
Все листьевые узлы должны удовлетворять пороговому ограничению &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, т.е. диаметр (радиус) не должен превосходить &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;.&lt;br /&gt;
В процессе вставки новых данных CF дерево строится динамически. Оно использует вставку данных для кластеризации точно также как &amp;lt;math&amp;gt;B+&amp;lt;/math&amp;gt; [https://ru.wikipedia.org/wiki/B%2B-%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE дерево] использует её для поиска.&lt;br /&gt;
CF дерево очень компактно, поскольку каждый листьевой узел - это не просто точка, а подкластер (который объединяет множество точек с учётом ограничения &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Операция вставки в &#039;&#039;&#039;CF&#039;&#039;&#039; дерево ====&lt;br /&gt;
&lt;br /&gt;
Опишем алгоритм вставки элемнта &amp;lt;math&amp;gt;Ent&amp;lt;/math&amp;gt; в CF дерево:&lt;br /&gt;
&lt;br /&gt;
1) &#039;&#039;Определение подходящего листа&#039;&#039;: Начиная с корня, алгоритм рекурсивно спускается по CF дереву, выбирая &#039;&#039;&#039;ближайший&#039;&#039;&#039; дочерний узел в соответствии с выбранной метрикой &amp;lt;math&amp;gt;D0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D4&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &#039;&#039;Преобразование листа&#039;&#039;: Когда алгоритм доходит до листа, он находит ближайшую листьевой элемент, скажем, &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;, а затем проверяет, можно ли добавить &#039;&#039;Ent&#039;&#039; к &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt; без нарушения порогового условия. Если да, то с учётом этого изменяется CF вектор для &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;; если нет, то &#039;&#039;Ent&#039;&#039; становится новым элементом листа. Если в листе для этого достаточно места, то шаг окончен, иначе он должен &amp;quot;расщепиться&amp;quot;. Расщепление узла производится при помощи выбора за основу наиболее удалённой друг от друга пары элементов и перераспределение оставшихся элементов в соответствии с выбранным критерием близости.&lt;br /&gt;
&lt;br /&gt;
3) &#039;&#039;Преобразование пути к листу&#039;&#039;: После вставки &#039;&#039;Ent&#039;&#039; в лист мы должны обновить информацию о CF для каждого нелистьевого элемента на пути к листу. При отсутствии расщепления это означает простое сложение CF векторов для отражения факта добавления &#039;&#039;Ent&#039;&#039;. Расщепление листа же требует вставки нового нелистьевого элемента в родительский узел для задания только что созданного листа. Если у родителя есть место для этого элемента, то необходимо просто преобразовать CF векторы на всех более высоких уровнях. В общем случае, однако, нам также придётся расщепить родительский узел, и так далее до корня. Если расщеплён корень, то высота дерева увеличивается на единицу.&lt;br /&gt;
&lt;br /&gt;
4) &#039;&#039;Улучшение слияния&#039;&#039;: Расщепление вызвано ограничением на размер узла, который не зависит от кластеризационных свойств данных. Если во входящем потоке присутствуют &amp;quot;искажённые&amp;quot; (из областей с низкой плотностью) данные, это может повлиять на качество кластеризации, а также уменьшить эффективность использования памяти. Дополнительный шаг алгоритма помогает решить эти проблемы: предположим, что произошло расщепление листа, и распространение этого процесса остановилось на некотором нелистьевом узле &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt;, то есть &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; может вместить дополнительный элемент, полученный после расщепления. Теперь мы сканируем узел &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; для нахождения двух наиболее близких элементов. Если это не пара, отвечающая расщеплению, мы пытаемся объединить их и поставить в соответствие два дочерних узла. Если количество элементов в дочерних узлах  больше B, мы снова расщепляем результат объединения.&lt;br /&gt;
В процессе повторного расщепления, в случае, если один источник собирает достаточно элементов для того, чтобы полностью заполнить узел, оставшиеся элементы передаются другом источнику. В итоге, если объединённые элементы помещаются в одном узле, в нём освобождается место для ещё одного элемента. Тем самым увеличивается степень использования свободного пространства и откладывается дальнейшее расщепление. В ином случае мы улучшаем распределение элементов в двух ближайших подкластерах.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро алгоритма заключается в многократном выполнении операции вставки нового элемента в дерево, в процессе чего требуется вычисление следующих величин:&lt;br /&gt;
&lt;br /&gt;
* радиуса &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; или диаметра &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластерного элемента. Выполняется при попытке вставить новый элемент в один из подкластеров листьевого узла дерева.&lt;br /&gt;
&lt;br /&gt;
* расстояния между двумя элементами. Выполняется при поиске ближайшего по отношению к новому элементу подкластера в узле дерева по одной из рассмотренных в разд. 1.2.1 метрик &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Зная характеристики кластерных элементов &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;, в результате алгебраических преобразований можно получить следующие упрощенные формулы вычисления необходимых значений:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\vec{X_0} = \frac{\vec{LS}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{SS - 2\vec{X_0}\vec{LS} + N(\vec{X_0})^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{2(N*SS - (\vec{LS})^2)}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{N_1*SS_2 + N_2*SS_1 - 2\vec{LS_1}\vec{LS_2}}{N_1*N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{2((N_1+N_2)(SS_1+SS_2)-(\vec{LS_1}+\vec{LS_2})^2)}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Реализация алгоритма BIRCH состояит из следующих четырёх фаз:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 1&#039;&#039;&#039;. Главной задачей фазы 1 является сканирование всех данных и построение в памяти исходного CF дерева, используя заданное количество памяти. Это дерево стремится отразить информацию о кластеризации данных настолько хорошо, насколько это позволяют ограничения по памяти. При этом плотно распределённые данные группируются в подкластеры, а более разрозненные данные удаляются. После завершения фазы 1 вспомогательные вычисления в дальнейших фазах будут:&lt;br /&gt;
&lt;br /&gt;
1) быстрее, потому что (а) больше не нужны операции ввода-вывода, (b) проблема кластеризации начальных данных упрощается до проблемы кластеризации подкластеров в листьях;&lt;br /&gt;
&lt;br /&gt;
2) точнее, потому что (а) большинство данных с низкой плотностью удалены, (b) оставшиеся данные распределены оптимально (в соответствии с доступным количеством памяти);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 2&#039;&#039;&#039;. Данная фаза является опциональной. Известно, что существующие методы глобальной кластеризации, используемые в рамках фазы 3, имеют различные диапазоны входных значений, при которых их реализация наиболее эффективна. Поэтому потенциально существует пробел между размером фазы 1 и входными значениями фазы 3. И фаза 2 как раз является недостающим связующим звеном: так же как и фаза 1, она сканирует листьевые элементы начального CF дерева для того, чтобы построить меньшее дерево, удаляя ещё больше элементов с низкой плотностью и группируя переполненные подкластеры в большие кластеры.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 3&#039;&#039;&#039;. В данной фазе для листьевых элементов применяется (любой подходящий) алгоритм глобальной кластеризации. Существующие алгоритмы кластеризации наборов точек могут также работать с наборами подкластеров, каждый из которых представлен своим CF вектором. Зная CF вектор, можно вычислить центроид и в дальнейшем заменить всю информацию о кластере этим значением (этого достаточно для вычисления большинства необходимых метрик). После фазы 3 мы получаем набор кластеров, который отражает основные характеристики распределяемых данных.&lt;br /&gt;
Однако, всё ещё могут оставаться некоторые неточности, для устранения которых существует фаза 4.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 4&#039;&#039;&#039;. Данная фаза является опциональной и влечёт за собой затраты на дополнительное сканирование данных для корректировки неточностей и дальнейшего улучшения кластеризации. Фаза 4 использует центроиды кластеров, полученные в фазе 3 для как основы и перераспределяет точки входных данных в ближайшие для них основы для получения нового списка кластеров. Фаза 4, если это необходимо пользователю, может быть расширена дополнительными проходами для уверенности в том, что результат приближается к оптимальному.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Для начала проанализируем вычислительную сложность фазы 1.&lt;br /&gt;
Максимальный размер дерева &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt;. Для того чтобы вставить элемент, мы должны пройти путь от корня до листа (это около &amp;lt;math&amp;gt;1+log_B\frac{M}{P}&amp;lt;/math&amp;gt; узлов). В каждом узле в поисках &amp;quot;ближайшего&amp;quot; нам необходимо просмотреть B элементов; сложность для каждого элемента пропорциональна размерности &#039;&#039;d&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Поэтому сложность вставки всех входных точек &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В случае, когда необходимо перестроить дерево, предположим, что ES - это размер CF элемента. Существует максимум &amp;lt;math&amp;gt;\frac{M}{ES}&amp;lt;\math&amp;gt; листьевых элементов для вставки, поэтому сложность повторной вставки листьевых элементов &amp;lt;math&amp;gt;O(d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Количество итераций перестройки дерева зависит от пороговой величины. На самом деле, это около &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; (двоичное основание появилось из-за того, что мы никогда не можем провести оценку более чем в 2 раза отличающуюся от текущего размера. &amp;lt;math&amp;gt;N_0&amp;lt;/math&amp;gt; - это число входных точек, загруженных в память с пороговым ограничением &amp;lt;math&amp;gt;T_0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Соответственно, итоговая сложность фазы 1 &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P})+log_2\frac{N}{N_0}*d*\frac{M}{ES}*B(1+log_B{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Анализ фазы 2 проводится аналогично.&lt;br /&gt;
&lt;br /&gt;
Что касается операций ввода-вывода, то в фазе 1 данные сканируются один раз, а в фазе 2 не сканируются вовсе.&lt;br /&gt;
Некоторое количество вычислений связано с удалением точек из областей с низкой плотностью.&lt;br /&gt;
Если количество доступной для этой операции памяти не больше &#039;&#039;M&#039;&#039; и проведено порядка &amp;lt;math&amp;gt;log_2{N}{N_0}&amp;lt;/math&amp;gt; перестроек дерева, то сложность ввода-вывода для фазы 1 не отличается существенно от сложности чтения из файла. Основываясь рассуждениях выше, сложность фаз 1 и 2 будет линейно увеличиваться с ростом N.&lt;br /&gt;
&lt;br /&gt;
В фазе 3 нет операций ввода-вывода. Сложность фазы 3 ограничена константой, которая зависит от максимального размера входных данных и варианта выбранного алгоритма для кластеризации. &lt;br /&gt;
&lt;br /&gt;
Фаза 4 снова сканирует данные и зписывает каждую точку в подходящий кластер; время работы пропорционально &amp;lt;math&amp;gt;N*K&amp;lt;/math&amp;gt;.   &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Достоинства алгоритма ===&lt;br /&gt;
По сравнению с предыдущими методами BIRCH обладает следующими достоинствами:&lt;br /&gt;
&lt;br /&gt;
1. BIRCH является локальным алгоритмом, то есть каждое решение о каждом элементе кластера принимается без повторного сканирования данных или уже существующих кластеров. Используются только метрики, отражающие близость элементов друг к другу.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH использует факт неравномерного распределения данных в пространстве и поэтому не все данные рассматриваются как одинаково важные для построения кластера. Области с большой плотностью обрабатываются как единый кластер. Данные в более разреженных областях могут удаляться (опционально).&lt;br /&gt;
&lt;br /&gt;
3. BIRCH использует всю доступную память для получения наилучших из возможных подкластеров, в то же время минимизируя затраты на операции ввода/вывода. Оптимизация процесса кластеризации достигается за счет использования взвешенно-сбалансированного дерева. При этом время исполнения линейно.&lt;br /&gt;
&lt;br /&gt;
4. BIRCH не требует всего набора данных заранее (при этом просматривает его всего один раз).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&lt;br /&gt;
[1] Википедия&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;/div&gt;</summary>
		<author><name>Светлана Морозова</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13491</id>
		<title>Участник:Smirnov.maxim/BIRCH</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13491"/>
		<updated>2016-10-23T09:28:01Z</updated>

		<summary type="html">&lt;p&gt;Светлана Морозова: /* Последовательная сложность алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Нахождение полезных для анализа закономерностей в больших объёмах данных с недавних пор вызывает значительный интерес. В связи с этим ввелось и стало активно развиваться такое понятие как &#039;&#039;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7 кластеризация]&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Ранние работы и алгоритмы, разработанные в этой области, не уделяли достаточного внимания анализу очень больших наборов данных или минимизации издержек на процессы ввода-вывода.&lt;br /&gt;
Решением этих проблем стал алгоритм, известный как BIRCH.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIRCH&#039;&#039;&#039; (balanced iterative reducing and clustering using hierarchies)- алгоритм, применяемый в области [https://ru.wikipedia.org/wiki/Data_mining Data mining] и использующий принципы [https://ru.wikipedia.org/wiki/%D0%98%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F иерархической кластеризации].&lt;br /&gt;
&lt;br /&gt;
Если имеется очень большой набор данных, то в пространстве он распределен, как правило, неравномерно. Кластерный анализ определяет места наибольшего и наименьшего скоплений, чтобы таким образом понять всю картину целиком. Кроме того, полученные кластеры визуализируются гораздо нагляднее, чем начальные &amp;quot;сырые&amp;quot; данные.&lt;br /&gt;
Задачей алгоритмов кластеризации является не только простое разбиение данных на кластеры, но и работа в рамках ограниченного объёма доступной памяти (как правило, её объём гораздо меньше, чем размер исходного набора данных) и минимизация времени, требуемого на операции ввода-вывода.&lt;br /&gt;
&lt;br /&gt;
Для наилучшего решения этих проблем BIRCH распределяет входящие данные по кластерам динамически. Для эффективной кластеризации алгоритму требуется всего одно сканирование данных (т.е. с увеличением количества данных сложность увеличивается линейно). А при помощи одной (или более) дополнительных итераций можно и далее улучшать эффективность. BIRCH также является первым алгоритмом, предложенным для эффективного управления &amp;quot;шумами&amp;quot; (данными, которые не вписываются в общее представление модели).&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Теоретическая основа ===&lt;br /&gt;
&lt;br /&gt;
Пусть в кластере имеются &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}, i=1,2,...,N&amp;lt;/math&amp;gt;.&lt;br /&gt;
Тогда &#039;&#039;&#039;центроид&#039;&#039;&#039; &amp;lt;math&amp;gt;{\vec{{X_0}}}&amp;lt;/math&amp;gt;, &#039;&#039;&#039;радиус&#039;&#039;&#039; &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &#039;&#039;&#039;диаметр&#039;&#039;&#039; &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластера определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;{\vec{X_0}}=\frac{\sum_{i=1}^N\vec{X_i}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{\sum_{i=1}^N{(\vec{X_i} - \vec{X_0})}^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{\sum_{i=1}^N\sum_{j=1}^N{(\vec{X_i} - \vec{X_j})}^2}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; - это среднее расстояние от каждой точки до центроида. &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; - это среднее расстояние между парами в кластере. Данные величины являются альтернативными метриками плотности кластера относительно центроида.&lt;br /&gt;
&lt;br /&gt;
Для измерения близости друг к другу двух кластеров вводятся следующие метрики:&lt;br /&gt;
&lt;br /&gt;
пусть даны центроиды двух кластеров &amp;lt;math&amp;gt;\vec{X_{01}}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\vec{X_{02}}&amp;lt;/math&amp;gt;.&lt;br /&gt;
Евклидова метрика &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt; и метрика Манхэттена &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt; между двумя кластерами определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_0 = ((\vec{X_{01}}-\vec{X_{02}})^2)^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_1 = |\vec{X_{01}}-\vec{X_{02}}| = \sum_{i=1}^d |{\vec{X_{01}}}^{(i)}-{\vec{X_{02}}}^{(i)}| &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть имеются два кластера, содержащих соответственно  &amp;lt;math&amp;gt;N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;N_2&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i= 1,2, ...,N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\{\vec{X_j}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j= N_1+1,N_1+2, ...,N_1+N_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Среднее расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &#039;&#039;&#039;среднее внутрикластерное расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &#039;&#039;&#039;дисперсия&#039;&#039;&#039; &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; для двух кластеров определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{\sum_{i=1}^{N_1}\sum_{j=N_1+1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{N_1N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{\sum_{i=1}^{N_1+N_2}\sum_{j=1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_4 = \sum_{k=1}^{N_1+N_2}(\vec{X_k} - \frac{\sum_{i=1}^{N_1+N_2}\vec{X_i}}{N_1+N_2})^2 - \sum_{i=1}^{N_1}(\vec{X_i} - \frac{\sum_{i=1}^{N_1}\vec{X_i}}{N_1})^2 - \sum_{j=N_1+1}^{N_1+N_2}(\vec{X_j} - \frac{\sum_{i=N_1+1}^{N_1+N_2}\vec{X_i}}{N_2})^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Таким образом, величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; относятся к отдельным кластерам, а &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; - к объединению двух кластеров.&lt;br /&gt;
&lt;br /&gt;
=== Кластерный элемент и кластерное дерево ===&lt;br /&gt;
&lt;br /&gt;
В основе концепции алгоритма BIRCH лежат понятия &#039;&#039;&#039;кластерного элемента&#039;&#039;&#039; и &#039;&#039;&#039;кластерного дерева (CF Tree)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====Кластерный элемент ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; Пусть в кластере содержатся  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности  &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;:&amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;i=1,2,...,N&amp;lt;/math&amp;gt;. &lt;br /&gt;
&#039;&#039;&#039;Кластерный элемент (CF)&#039;&#039;&#039; - тройка чисел, характеризующая информацию о кластере: &lt;br /&gt;
&amp;lt;math&amp;gt;CF = (N, \vec{LS}, SS)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - количество элементов входных данных, содержащихся в кластере, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; - линейная сумма входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}\vec{X_i}&amp;lt;/math&amp;gt;), &amp;lt;math&amp;gt;SS&amp;lt;/math&amp;gt; - сумма квадратов входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}{\vec{X_i}}^2&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Теорема&#039;&#039;&#039; Пусть &amp;lt;math&amp;gt;CF_1 = (N_1, \vec{LS_1}, SS_1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;CF_2 = (N_1, \vec{LS_2}, SS_2)&amp;lt;/math&amp;gt; - CF векторы двух непересекающихся кластеров. Тогда при их объединении образуется кластер со следующим CF вектором: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF = CF_1 + CF_2 = (N_1+N_2, \vec{LS_1}+\vec{LS_2}, SS_1+SS_2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Из указанных выше определения и теоремы вытекает тот факт, что при объединении кластеров их CF вектор может вычисляться инкрементно и точно. &lt;br /&gt;
Легко показать, что вычислить величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;, как и обычные метрики, также не составит труда.&lt;br /&gt;
&lt;br /&gt;
Таким образом, в данном случае информацией о кластере является не весь набор точек, а вектор CF. Хранение одного только вектора может показаться неэффективным, но этого вполне достаточно для оперирования всеми необходимыми метриками, на основе которых принимаются решения в алгоритме BIRCH.&lt;br /&gt;
&lt;br /&gt;
==== Кластерное дерево ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; &#039;&#039;&#039;Кластерное дерево (CF Tree)&#039;&#039;&#039; - это взвешенно сбалансированное дерево с двумя параметрами: &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - коэффициент разветвления, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - пороговая величина. Каждый нелистьевой узел дерева имеет не более чем &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; вхождений узлов следующей формы: &amp;lt;math&amp;gt;[CF_i,child_i]&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i=1,2,...,B&amp;lt;/math&amp;gt;, &#039;&#039;child&#039;&#039; - указатель на i-й дочерний узел, &amp;lt;math&amp;gt;CF_i&amp;lt;/math&amp;gt; - CF вектор соответствующего подкластера.&lt;br /&gt;
&lt;br /&gt;
Каждый листьевой узел имеет ссылку на два соседних узла (&#039;&#039;prev&#039;&#039; и &#039;&#039;next&#039;&#039;) для того, чтобы связать все узлы для эффективного сканирования.&lt;br /&gt;
Все листьевые узлы должны удовлетворять пороговому ограничению &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, т.е. диаметр (радиус) не должен превосходить &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;.&lt;br /&gt;
В процессе вставки новых данных CF дерево строится динамически. Оно использует вставку данных для кластеризации точно также как &amp;lt;math&amp;gt;B+&amp;lt;/math&amp;gt; [https://ru.wikipedia.org/wiki/B%2B-%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE дерево] использует её для поиска.&lt;br /&gt;
CF дерево очень компактно, поскольку каждый листьевой узел - это не просто точка, а подкластер (который объединяет множество точек с учётом ограничения &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Операция вставки в &#039;&#039;&#039;CF&#039;&#039;&#039; дерево ====&lt;br /&gt;
&lt;br /&gt;
Опишем алгоритм вставки элемнта &amp;lt;math&amp;gt;Ent&amp;lt;/math&amp;gt; в CF дерево:&lt;br /&gt;
&lt;br /&gt;
1) &#039;&#039;Определение подходящего листа&#039;&#039;: Начиная с корня, алгоритм рекурсивно спускается по CF дереву, выбирая &#039;&#039;&#039;ближайший&#039;&#039;&#039; дочерний узел в соответствии с выбранной метрикой &amp;lt;math&amp;gt;D0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D4&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &#039;&#039;Преобразование листа&#039;&#039;: Когда алгоритм доходит до листа, он находит ближайшую листьевой элемент, скажем, &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;, а затем проверяет, можно ли добавить &#039;&#039;Ent&#039;&#039; к &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt; без нарушения порогового условия. Если да, то с учётом этого изменяется CF вектор для &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;; если нет, то &#039;&#039;Ent&#039;&#039; становится новым элементом листа. Если в листе для этого достаточно места, то шаг окончен, иначе он должен &amp;quot;расщепиться&amp;quot;. Расщепление узла производится при помощи выбора за основу наиболее удалённой друг от друга пары элементов и перераспределение оставшихся элементов в соответствии с выбранным критерием близости.&lt;br /&gt;
&lt;br /&gt;
3) &#039;&#039;Преобразование пути к листу&#039;&#039;: После вставки &#039;&#039;Ent&#039;&#039; в лист мы должны обновить информацию о CF для каждого нелистьевого элемента на пути к листу. При отсутствии расщепления это означает простое сложение CF векторов для отражения факта добавления &#039;&#039;Ent&#039;&#039;. Расщепление листа же требует вставки нового нелистьевого элемента в родительский узел для задания только что созданного листа. Если у родителя есть место для этого элемента, то необходимо просто преобразовать CF векторы на всех более высоких уровнях. В общем случае, однако, нам также придётся расщепить родительский узел, и так далее до корня. Если расщеплён корень, то высота дерева увеличивается на единицу.&lt;br /&gt;
&lt;br /&gt;
4) &#039;&#039;Улучшение слияния&#039;&#039;: Расщепление вызвано ограничением на размер узла, который не зависит от кластеризационных свойств данных. Если во входящем потоке присутствуют &amp;quot;искажённые&amp;quot; (из областей с низкой плотностью) данные, это может повлиять на качество кластеризации, а также уменьшить эффективность использования памяти. Дополнительный шаг алгоритма помогает решить эти проблемы: предположим, что произошло расщепление листа, и распространение этого процесса остановилось на некотором нелистьевом узле &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt;, то есть &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; может вместить дополнительный элемент, полученный после расщепления. Теперь мы сканируем узел &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; для нахождения двух наиболее близких элементов. Если это не пара, отвечающая расщеплению, мы пытаемся объединить их и поставить в соответствие два дочерних узла. Если количество элементов в дочерних узлах  больше B, мы снова расщепляем результат объединения.&lt;br /&gt;
В процессе повторного расщепления, в случае, если один источник собирает достаточно элементов для того, чтобы полностью заполнить узел, оставшиеся элементы передаются другом источнику. В итоге, если объединённые элементы помещаются в одном узле, в нём освобождается место для ещё одного элемента. Тем самым увеличивается степень использования свободного пространства и откладывается дальнейшее расщепление. В ином случае мы улучшаем распределение элементов в двух ближайших подкластерах.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро алгоритма заключается в многократном выполнении операции вставки нового элемента в дерево, в процессе чего требуется вычисление следующих величин:&lt;br /&gt;
&lt;br /&gt;
* радиуса &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; или диаметра &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластерного элемента. Выполняется при попытке вставить новый элемент в один из подкластеров листьевого узла дерева.&lt;br /&gt;
&lt;br /&gt;
* расстояния между двумя элементами. Выполняется при поиске ближайшего по отношению к новому элементу подкластера в узле дерева по одной из рассмотренных в разд. 1.2.1 метрик &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Зная характеристики кластерных элементов &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;, в результате алгебраических преобразований можно получить следующие упрощенные формулы вычисления необходимых значений:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\vec{X_0} = \frac{\vec{LS}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{SS - 2\vec{X_0}\vec{LS} + N(\vec{X_0})^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{2(N*SS - (\vec{LS})^2)}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{N_1*SS_2 + N_2*SS_1 - 2\vec{LS_1}\vec{LS_2}}{N_1*N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{2((N_1+N_2)(SS_1+SS_2)-(\vec{LS_1}+\vec{LS_2})^2)}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Реализация алгоритма BIRCH состояит из следующих четырёх фаз:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 1&#039;&#039;&#039;. Главной задачей фазы 1 является сканирование всех данных и построение в памяти исходного CF дерева, используя заданное количество памяти. Это дерево стремится отразить информацию о кластеризации данных настолько хорошо, насколько это позволяют ограничения по памяти. При этом плотно распределённые данные группируются в подкластеры, а более разрозненные данные удаляются. После завершения фазы 1 вспомогательные вычисления в дальнейших фазах будут:&lt;br /&gt;
&lt;br /&gt;
1) быстрее, потому что (а) больше не нужны операции ввода-вывода, (b) проблема кластеризации начальных данных упрощается до проблемы кластеризации подкластеров в листьях;&lt;br /&gt;
&lt;br /&gt;
2) точнее, потому что (а) большинство данных с низкой плотностью удалены, (b) оставшиеся данные распределены оптимально (в соответствии с доступным количеством памяти);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 2&#039;&#039;&#039;. Данная фаза является опциональной. Известно, что существующие методы глобальной кластеризации, используемые в рамках фазы 3, имеют различные диапазоны входных значений, при которых их реализация наиболее эффективна. Поэтому потенциально существует пробел между размером фазы 1 и входными значениями фазы 3. И фаза 2 как раз является недостающим связующим звеном: так же как и фаза 1, она сканирует листьевые элементы начального CF дерева для того, чтобы построить меньшее дерево, удаляя ещё больше элементов с низкой плотностью и группируя переполненные подкластеры в большие кластеры.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 3&#039;&#039;&#039;. В данной фазе для листьевых элементов применяется (любой подходящий) алгоритм глобальной кластеризации. Существующие алгоритмы кластеризации наборов точек могут также работать с наборами подкластеров, каждый из которых представлен своим CF вектором. Зная CF вектор, можно вычислить центроид и в дальнейшем заменить всю информацию о кластере этим значением (этого достаточно для вычисления большинства необходимых метрик). После фазы 3 мы получаем набор кластеров, который отражает основные характеристики распределяемых данных.&lt;br /&gt;
Однако, всё ещё могут оставаться некоторые неточности, для устранения которых существует фаза 4.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 4&#039;&#039;&#039;. Данная фаза является опциональной и влечёт за собой затраты на дополнительное сканирование данных для корректировки неточностей и дальнейшего улучшения кластеризации. Фаза 4 использует центроиды кластеров, полученные в фазе 3 для как основы и перераспределяет точки входных данных в ближайшие для них основы для получения нового списка кластеров. Фаза 4, если это необходимо пользователю, может быть расширена дополнительными проходами для уверенности в том, что результат приближается к оптимальному.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Для начала проанализируем вычислительную сложность фазы 1.&lt;br /&gt;
Максимальный размер дерева &amp;lt;math&amp;gt;\frac{M}{P}&amp;lt;/math&amp;gt;. Для того чтобы вставить элемент мы должны пройти путь от корня до листа, пройдя около &amp;lt;math&amp;gt;1+lob_B\frac{M}{P}&amp;lt;/math&amp;gt; узлов. В каждом узле в поисках &amp;quot;ближайшего&amp;quot; нам необходимо просмотреть B элементов; сложность для каждого элемента пропорциональна размерности &#039;&#039;d&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Поэтому сложность вставки всех входных точек &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В случае, когда необходимо перестроить дерево, предположим, что ES - это размер CF элемента. Существует максимум &amp;lt;math&amp;gt;\frac{M}{ES}&amp;lt;\math&amp;gt; листьевых элементов для вставки, поэтому сложность повторной вставки листьевых элементов &amp;lt;math&amp;gt;O(d*\frac{M}{ES}*B(1+log_B\frac{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Количество итераций перестройки дерева зависит от пороговой величины. На самом деле, это около &amp;lt;math&amp;gt;log_2\frac{N}{N_0}&amp;lt;/math&amp;gt; (двоичное основание появилось из-за того, что мы никогда не можем провести оценку более чем в 2 раза отличающуюся от текущего размера. &amp;lt;math&amp;gt;N_0&amp;lt;/math&amp;gt; - это число входных точек, загруженных в память с пороговым ограничением &amp;lt;math&amp;gt;T_0&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Соответственно, итоговая сложность фазы 1 &amp;lt;math&amp;gt;O(d*N*B(1+log_B\frac{M}{P})+log_2\frac{N}{N_0}*d*\frac{M}{ES}*B(1+log_B{M}{P}))&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Анализ фазы 2 проводится аналогично.&lt;br /&gt;
&lt;br /&gt;
Что касается операций ввода-вывода, то в фазе 1 данные сканируются один раз, а в фазе 2 не сканируются вовсе.&lt;br /&gt;
Некоторое количество вычислений связано с удалением точек из областей с низкой плотностью.&lt;br /&gt;
Если количество доступной для этой операции памяти не больше &#039;&#039;M&#039;&#039; и проведено порядка &amp;lt;math&amp;gt;log_2{N}{N_0}&amp;lt;/math&amp;gt; перестроек дерева, то сложность ввода-вывода для фазы 1 не отличается существенно от сложности чтения из файла. Основываясь рассуждениях выше, сложность фаз 1 и 2 будет линейно увеличиваться с ростом N.&lt;br /&gt;
&lt;br /&gt;
В фазе 3 нет операций ввода-вывода. Сложность фазы 3 ограничена константой, которая зависит от максимального размера входных данных и варианта выбранного алгоритма для кластеризации. &lt;br /&gt;
&lt;br /&gt;
Фаза 4 снова сканирует данные и зписывает каждую точку в подходящий кластер; время работы пропорционально &amp;lt;math&amp;gt;N*K&amp;lt;/math&amp;gt;.   &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Достоинства алгоритма ===&lt;br /&gt;
По сравнению с предыдущими методами BIRCH обладает следующими достоинствами:&lt;br /&gt;
&lt;br /&gt;
1. BIRCH является локальным алгоритмом, то есть каждое решение о каждом элементе кластера принимается без повторного сканирования данных или уже существующих кластеров. Используются только метрики, отражающие близость элементов друг к другу.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH использует факт неравномерного распределения данных в пространстве и поэтому не все данные рассматриваются как одинаково важные для построения кластера. Области с большой плотностью обрабатываются как единый кластер. Данные в более разреженных областях могут удаляться (опционально).&lt;br /&gt;
&lt;br /&gt;
3. BIRCH использует всю доступную память для получения наилучших из возможных подкластеров, в то же время минимизируя затраты на операции ввода/вывода. Оптимизация процесса кластеризации достигается за счет использования взвешенно-сбалансированного дерева. При этом время исполнения линейно.&lt;br /&gt;
&lt;br /&gt;
4. BIRCH не требует всего набора данных заранее (при этом просматривает его всего один раз).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&lt;br /&gt;
[1] Википедия&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;/div&gt;</summary>
		<author><name>Светлана Морозова</name></author>
	</entry>
	<entry>
		<id>https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13490</id>
		<title>Участник:Smirnov.maxim/BIRCH</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:Smirnov.maxim/BIRCH&amp;diff=13490"/>
		<updated>2016-10-23T08:56:59Z</updated>

		<summary type="html">&lt;p&gt;Светлана Морозова: /* Вычислительное ядро алгоритма */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Общее описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Нахождение полезных для анализа закономерностей в больших объёмах данных с недавних пор вызывает значительный интерес. В связи с этим ввелось и стало активно развиваться такое понятие как &#039;&#039;[https://ru.wikipedia.org/wiki/%D0%9A%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%BD%D1%8B%D0%B9_%D0%B0%D0%BD%D0%B0%D0%BB%D0%B8%D0%B7 кластеризация]&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Ранние работы и алгоритмы, разработанные в этой области, не уделяли достаточного внимания анализу очень больших наборов данных или минимизации издержек на процессы ввода-вывода.&lt;br /&gt;
Решением этих проблем стал алгоритм, известный как BIRCH.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;BIRCH&#039;&#039;&#039; (balanced iterative reducing and clustering using hierarchies)- алгоритм, применяемый в области [https://ru.wikipedia.org/wiki/Data_mining Data mining] и использующий принципы [https://ru.wikipedia.org/wiki/%D0%98%D0%B5%D1%80%D0%B0%D1%80%D1%85%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F иерархической кластеризации].&lt;br /&gt;
&lt;br /&gt;
Если имеется очень большой набор данных, то в пространстве он распределен, как правило, неравномерно. Кластерный анализ определяет места наибольшего и наименьшего скоплений, чтобы таким образом понять всю картину целиком. Кроме того, полученные кластеры визуализируются гораздо нагляднее, чем начальные &amp;quot;сырые&amp;quot; данные.&lt;br /&gt;
Задачей алгоритмов кластеризации является не только простое разбиение данных на кластеры, но и работа в рамках ограниченного объёма доступной памяти (как правило, её объём гораздо меньше, чем размер исходного набора данных) и минимизация времени, требуемого на операции ввода-вывода.&lt;br /&gt;
&lt;br /&gt;
Для наилучшего решения этих проблем BIRCH распределяет входящие данные по кластерам динамически. Для эффективной кластеризации алгоритму требуется всего одно сканирование данных (т.е. с увеличением количества данных сложность увеличивается линейно). А при помощи одной (или более) дополнительных итераций можно и далее улучшать эффективность. BIRCH также является первым алгоритмом, предложенным для эффективного управления &amp;quot;шумами&amp;quot; (данными, которые не вписываются в общее представление модели).&lt;br /&gt;
&lt;br /&gt;
== Математическое описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Теоретическая основа ===&lt;br /&gt;
&lt;br /&gt;
Пусть в кластере имеются &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}, i=1,2,...,N&amp;lt;/math&amp;gt;.&lt;br /&gt;
Тогда &#039;&#039;&#039;центроид&#039;&#039;&#039; &amp;lt;math&amp;gt;{\vec{{X_0}}}&amp;lt;/math&amp;gt;, &#039;&#039;&#039;радиус&#039;&#039;&#039; &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &#039;&#039;&#039;диаметр&#039;&#039;&#039; &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластера определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;{\vec{X_0}}=\frac{\sum_{i=1}^N\vec{X_i}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{\sum_{i=1}^N{(\vec{X_i} - \vec{X_0})}^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{\sum_{i=1}^N\sum_{j=1}^N{(\vec{X_i} - \vec{X_j})}^2}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; - это среднее расстояние от каждой точки до центроида. &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; - это среднее расстояние между парами в кластере. Данные величины являются альтернативными метриками плотности кластера относительно центроида.&lt;br /&gt;
&lt;br /&gt;
Для измерения близости друг к другу двух кластеров вводятся следующие метрики:&lt;br /&gt;
&lt;br /&gt;
пусть даны центроиды двух кластеров &amp;lt;math&amp;gt;\vec{X_{01}}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\vec{X_{02}}&amp;lt;/math&amp;gt;.&lt;br /&gt;
Евклидова метрика &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt; и метрика Манхэттена &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt; между двумя кластерами определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_0 = ((\vec{X_{01}}-\vec{X_{02}})^2)^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_1 = |\vec{X_{01}}-\vec{X_{02}}| = \sum_{i=1}^d |{\vec{X_{01}}}^{(i)}-{\vec{X_{02}}}^{(i)}| &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Пусть имеются два кластера, содержащих соответственно  &amp;lt;math&amp;gt;N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;N_2&amp;lt;/math&amp;gt; точек размерности &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;: &amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i= 1,2, ...,N_1&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;\{\vec{X_j}\}&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;j= N_1+1,N_1+2, ...,N_1+N_2&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Среднее расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &#039;&#039;&#039;среднее внутрикластерное расстояние&#039;&#039;&#039; &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &#039;&#039;&#039;дисперсия&#039;&#039;&#039; &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; для двух кластеров определяются следующим образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{\sum_{i=1}^{N_1}\sum_{j=N_1+1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{N_1N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{\sum_{i=1}^{N_1+N_2}\sum_{j=1}^{N_1+N_2}{(\vec{X_i} - \vec{X_j})}^2}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_4 = \sum_{k=1}^{N_1+N_2}(\vec{X_k} - \frac{\sum_{i=1}^{N_1+N_2}\vec{X_i}}{N_1+N_2})^2 - \sum_{i=1}^{N_1}(\vec{X_i} - \frac{\sum_{i=1}^{N_1}\vec{X_i}}{N_1})^2 - \sum_{j=N_1+1}^{N_1+N_2}(\vec{X_j} - \frac{\sum_{i=N_1+1}^{N_1+N_2}\vec{X_i}}{N_2})^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Таким образом, величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; относятся к отдельным кластерам, а &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt; - к объединению двух кластеров.&lt;br /&gt;
&lt;br /&gt;
=== Кластерный элемент и кластерное дерево ===&lt;br /&gt;
&lt;br /&gt;
В основе концепции алгоритма BIRCH лежат понятия &#039;&#039;&#039;кластерного элемента&#039;&#039;&#039; и &#039;&#039;&#039;кластерного дерева (CF Tree)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
====Кластерный элемент ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; Пусть в кластере содержатся  &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; точек размерности  &amp;lt;math&amp;gt;d&amp;lt;/math&amp;gt;:&amp;lt;math&amp;gt;\{\vec{X_i}\}&amp;lt;/math&amp;gt;, где  &amp;lt;math&amp;gt;i=1,2,...,N&amp;lt;/math&amp;gt;. &lt;br /&gt;
&#039;&#039;&#039;Кластерный элемент (CF)&#039;&#039;&#039; - тройка чисел, характеризующая информацию о кластере: &lt;br /&gt;
&amp;lt;math&amp;gt;CF = (N, \vec{LS}, SS)&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt; - количество элементов входных данных, содержащихся в кластере, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; - линейная сумма входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}\vec{X_i}&amp;lt;/math&amp;gt;), &amp;lt;math&amp;gt;SS&amp;lt;/math&amp;gt; - сумма квадратов входных данных (т.е. &amp;lt;math&amp;gt;\sum_{i=1}^{N}{\vec{X_i}}^2&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Теорема&#039;&#039;&#039; Пусть &amp;lt;math&amp;gt;CF_1 = (N_1, \vec{LS_1}, SS_1)&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;CF_2 = (N_1, \vec{LS_2}, SS_2)&amp;lt;/math&amp;gt; - CF векторы двух непересекающихся кластеров. Тогда при их объединении образуется кластер со следующим CF вектором: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;CF = CF_1 + CF_2 = (N_1+N_2, \vec{LS_1}+\vec{LS_2}, SS_1+SS_2)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Из указанных выше определения и теоремы вытекает тот факт, что при объединении кластеров их CF вектор может вычисляться инкрементно и точно. &lt;br /&gt;
Легко показать, что вычислить величины &amp;lt;math&amp;gt;\vec{X_0}&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;, как и обычные метрики, также не составит труда.&lt;br /&gt;
&lt;br /&gt;
Таким образом, в данном случае информацией о кластере является не весь набор точек, а вектор CF. Хранение одного только вектора может показаться неэффективным, но этого вполне достаточно для оперирования всеми необходимыми метриками, на основе которых принимаются решения в алгоритме BIRCH.&lt;br /&gt;
&lt;br /&gt;
==== Кластерное дерево ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Определение.&#039;&#039; &#039;&#039;&#039;Кластерное дерево (CF Tree)&#039;&#039;&#039; - это взвешенно сбалансированное дерево с двумя параметрами: &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; - коэффициент разветвления, &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; - пороговая величина. Каждый нелистьевой узел дерева имеет не более чем &amp;lt;math&amp;gt;B&amp;lt;/math&amp;gt; вхождений узлов следующей формы: &amp;lt;math&amp;gt;[CF_i,child_i]&amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;i=1,2,...,B&amp;lt;/math&amp;gt;, &#039;&#039;child&#039;&#039; - указатель на i-й дочерний узел, &amp;lt;math&amp;gt;CF_i&amp;lt;/math&amp;gt; - CF вектор соответствующего подкластера.&lt;br /&gt;
&lt;br /&gt;
Каждый листьевой узел имеет ссылку на два соседних узла (&#039;&#039;prev&#039;&#039; и &#039;&#039;next&#039;&#039;) для того, чтобы связать все узлы для эффективного сканирования.&lt;br /&gt;
Все листьевые узлы должны удовлетворять пороговому ограничению &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;, т.е. диаметр (радиус) не должен превосходить &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;.&lt;br /&gt;
В процессе вставки новых данных CF дерево строится динамически. Оно использует вставку данных для кластеризации точно также как &amp;lt;math&amp;gt;B+&amp;lt;/math&amp;gt; [https://ru.wikipedia.org/wiki/B%2B-%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE дерево] использует её для поиска.&lt;br /&gt;
CF дерево очень компактно, поскольку каждый листьевой узел - это не просто точка, а подкластер (который объединяет множество точек с учётом ограничения &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== Операция вставки в &#039;&#039;&#039;CF&#039;&#039;&#039; дерево ====&lt;br /&gt;
&lt;br /&gt;
Опишем алгоритм вставки элемнта &amp;lt;math&amp;gt;Ent&amp;lt;/math&amp;gt; в CF дерево:&lt;br /&gt;
&lt;br /&gt;
1) &#039;&#039;Определение подходящего листа&#039;&#039;: Начиная с корня, алгоритм рекурсивно спускается по CF дереву, выбирая &#039;&#039;&#039;ближайший&#039;&#039;&#039; дочерний узел в соответствии с выбранной метрикой &amp;lt;math&amp;gt;D0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D4&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
2) &#039;&#039;Преобразование листа&#039;&#039;: Когда алгоритм доходит до листа, он находит ближайшую листьевой элемент, скажем, &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;, а затем проверяет, можно ли добавить &#039;&#039;Ent&#039;&#039; к &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt; без нарушения порогового условия. Если да, то с учётом этого изменяется CF вектор для &amp;lt;math&amp;gt;L_1&amp;lt;/math&amp;gt;; если нет, то &#039;&#039;Ent&#039;&#039; становится новым элементом листа. Если в листе для этого достаточно места, то шаг окончен, иначе он должен &amp;quot;расщепиться&amp;quot;. Расщепление узла производится при помощи выбора за основу наиболее удалённой друг от друга пары элементов и перераспределение оставшихся элементов в соответствии с выбранным критерием близости.&lt;br /&gt;
&lt;br /&gt;
3) &#039;&#039;Преобразование пути к листу&#039;&#039;: После вставки &#039;&#039;Ent&#039;&#039; в лист мы должны обновить информацию о CF для каждого нелистьевого элемента на пути к листу. При отсутствии расщепления это означает простое сложение CF векторов для отражения факта добавления &#039;&#039;Ent&#039;&#039;. Расщепление листа же требует вставки нового нелистьевого элемента в родительский узел для задания только что созданного листа. Если у родителя есть место для этого элемента, то необходимо просто преобразовать CF векторы на всех более высоких уровнях. В общем случае, однако, нам также придётся расщепить родительский узел, и так далее до корня. Если расщеплён корень, то высота дерева увеличивается на единицу.&lt;br /&gt;
&lt;br /&gt;
4) &#039;&#039;Улучшение слияния&#039;&#039;: Расщепление вызвано ограничением на размер узла, который не зависит от кластеризационных свойств данных. Если во входящем потоке присутствуют &amp;quot;искажённые&amp;quot; (из областей с низкой плотностью) данные, это может повлиять на качество кластеризации, а также уменьшить эффективность использования памяти. Дополнительный шаг алгоритма помогает решить эти проблемы: предположим, что произошло расщепление листа, и распространение этого процесса остановилось на некотором нелистьевом узле &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt;, то есть &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; может вместить дополнительный элемент, полученный после расщепления. Теперь мы сканируем узел &amp;lt;math&amp;gt;N_j&amp;lt;/math&amp;gt; для нахождения двух наиболее близких элементов. Если это не пара, отвечающая расщеплению, мы пытаемся объединить их и поставить в соответствие два дочерних узла. Если количество элементов в дочерних узлах  больше B, мы снова расщепляем результат объединения.&lt;br /&gt;
В процессе повторного расщепления, в случае, если один источник собирает достаточно элементов для того, чтобы полностью заполнить узел, оставшиеся элементы передаются другом источнику. В итоге, если объединённые элементы помещаются в одном узле, в нём освобождается место для ещё одного элемента. Тем самым увеличивается степень использования свободного пространства и откладывается дальнейшее расщепление. В ином случае мы улучшаем распределение элементов в двух ближайших подкластерах.&lt;br /&gt;
&lt;br /&gt;
== Вычислительное ядро алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Вычислительное ядро алгоритма заключается в многократном выполнении операции вставки нового элемента в дерево, в процессе чего требуется вычисление следующих величин:&lt;br /&gt;
&lt;br /&gt;
* радиуса &amp;lt;math&amp;gt;R&amp;lt;/math&amp;gt; или диаметра &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; кластерного элемента. Выполняется при попытке вставить новый элемент в один из подкластеров листьевого узла дерева.&lt;br /&gt;
&lt;br /&gt;
* расстояния между двумя элементами. Выполняется при поиске ближайшего по отношению к новому элементу подкластера в узле дерева по одной из рассмотренных в разд. 1.2.1 метрик &amp;lt;math&amp;gt;D_0&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;D_3&amp;lt;/math&amp;gt; или &amp;lt;math&amp;gt;D_4&amp;lt;/math&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Зная характеристики кластерных элементов &amp;lt;math&amp;gt;N&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;\vec{LS}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;S&amp;lt;/math&amp;gt;, в результате алгебраических преобразований можно получить следующие упрощенные формулы вычисления необходимых значений:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\vec{X_0} = \frac{\vec{LS}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;R = (\frac{SS - 2\vec{X_0}\vec{LS} + N(\vec{X_0})^2}{N})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D = (\frac{2(N*SS - (\vec{LS})^2)}{N(N-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_2 = (\frac{N_1*SS_2 + N_2*SS_1 - 2\vec{LS_1}\vec{LS_2}}{N_1*N_2})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;D_3 = (\frac{2((N_1+N_2)(SS_1+SS_2)-(\vec{LS_1}+\vec{LS_2})^2)}{(N_1+N_2)(N_1+N_2-1)})^{1/2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Макроструктура алгоритма ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Реализация алгоритма BIRCH состояит из следующих четырёх фаз:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 1&#039;&#039;&#039;. Главной задачей фазы 1 является сканирование всех данных и построение в памяти исходного CF дерева, используя заданное количество памяти. Это дерево стремится отразить информацию о кластеризации данных настолько хорошо, насколько это позволяют ограничения по памяти. При этом плотно распределённые данные группируются в подкластеры, а более разрозненные данные удаляются. После завершения фазы 1 вспомогательные вычисления в дальнейших фазах будут:&lt;br /&gt;
&lt;br /&gt;
1) быстрее, потому что (а) больше не нужны операции ввода-вывода, (b) проблема кластеризации начальных данных упрощается до проблемы кластеризации подкластеров в листьях;&lt;br /&gt;
&lt;br /&gt;
2) точнее, потому что (а) большинство данных с низкой плотностью удалены, (b) оставшиеся данные распределены оптимально (в соответствии с доступным количеством памяти);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 2&#039;&#039;&#039;. Данная фаза является опциональной. Известно, что существующие методы глобальной кластеризации, используемые в рамках фазы 3, имеют различные диапазоны входных значений, при которых их реализация наиболее эффективна. Поэтому потенциально существует пробел между размером фазы 1 и входными значениями фазы 3. И фаза 2 как раз является недостающим связующим звеном: так же как и фаза 1, она сканирует листьевые элементы начального CF дерева для того, чтобы построить меньшее дерево, удаляя ещё больше элементов с низкой плотностью и группируя переполненные подкластеры в большие кластеры.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 3&#039;&#039;&#039;. В данной фазе для листьевых элементов применяется (любой подходящий) алгоритм глобальной кластеризации. Существующие алгоритмы кластеризации наборов точек могут также работать с наборами подкластеров, каждый из которых представлен своим CF вектором. Зная CF вектор, можно вычислить центроид и в дальнейшем заменить всю информацию о кластере этим значением (этого достаточно для вычисления большинства необходимых метрик). После фазы 3 мы получаем набор кластеров, который отражает основные характеристики распределяемых данных.&lt;br /&gt;
Однако, всё ещё могут оставаться некоторые неточности, для устранения которых существует фаза 4.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Фаза 4&#039;&#039;&#039;. Данная фаза является опциональной и влечёт за собой затраты на дополнительное сканирование данных для корректировки неточностей и дальнейшего улучшения кластеризации. Фаза 4 использует центроиды кластеров, полученные в фазе 3 для как основы и перераспределяет точки входных данных в ближайшие для них основы для получения нового списка кластеров. Фаза 4, если это необходимо пользователю, может быть расширена дополнительными проходами для уверенности в том, что результат приближается к оптимальному.&lt;br /&gt;
&lt;br /&gt;
== Схема реализации последовательного алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Последовательная сложность алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Информационный граф ==&lt;br /&gt;
&lt;br /&gt;
== Ресурс параллелизма алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Входные и выходные данные алгоритма ==&lt;br /&gt;
&lt;br /&gt;
== Свойства алгоритма ==&lt;br /&gt;
&lt;br /&gt;
=== Достоинства алгоритма ===&lt;br /&gt;
По сравнению с предыдущими методами BIRCH обладает следующими достоинствами:&lt;br /&gt;
&lt;br /&gt;
1. BIRCH является локальным алгоритмом, то есть каждое решение о каждом элементе кластера принимается без повторного сканирования данных или уже существующих кластеров. Используются только метрики, отражающие близость элементов друг к другу.&lt;br /&gt;
&lt;br /&gt;
2. BIRCH использует факт неравномерного распределения данных в пространстве и поэтому не все данные рассматриваются как одинаково важные для построения кластера. Области с большой плотностью обрабатываются как единый кластер. Данные в более разреженных областях могут удаляться (опционально).&lt;br /&gt;
&lt;br /&gt;
3. BIRCH использует всю доступную память для получения наилучших из возможных подкластеров, в то же время минимизируя затраты на операции ввода/вывода. Оптимизация процесса кластеризации достигается за счет использования взвешенно-сбалансированного дерева. При этом время исполнения линейно.&lt;br /&gt;
&lt;br /&gt;
4. BIRCH не требует всего набора данных заранее (при этом просматривает его всего один раз).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= ЧАСТЬ. Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
= Литература =&lt;br /&gt;
&lt;br /&gt;
[1] Википедия&lt;br /&gt;
== Особенности реализации последовательного алгоритма ==&lt;/div&gt;</summary>
		<author><name>Светлана Морозова</name></author>
	</entry>
</feed>