<?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%9F%D0%B0%D0%B2%D0%B5%D0%BB</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%9F%D0%B0%D0%B2%D0%B5%D0%BB"/>
	<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%9F%D0%B0%D0%B2%D0%B5%D0%BB"/>
	<updated>2026-10-22T16:05:16Z</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:%D0%9F%D0%B0%D0%B2%D0%B5%D0%BB/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BA%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D0%B9%D0%BD%D1%8B%D1%85_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85_CLOPE&amp;diff=22502</id>
		<title>Участник:Павел/Алгоритм кластеризации категорийных данных CLOPE</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9F%D0%B0%D0%B2%D0%B5%D0%BB/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BA%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D0%B9%D0%BD%D1%8B%D1%85_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85_CLOPE&amp;diff=22502"/>
		<updated>2017-02-15T08:39:31Z</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;
Алгоритм CLOPE (Clustering with sLOPE&amp;lt;ref&amp;gt;Yang, Y., Guan, H., You. J. CLOPE: A fast and Effective Clustering Algorithm for Transactional Data In Proc. of SIGKDD’02, July 23-26, 2002, Edmonton, Alberta, Canada.&amp;lt;/ref&amp;gt;) неирархический метод кластеризации, предназначенный для кластеризации огромных наборов категорийных данных. К достоинствам алгоритма относятся высокие масштабируемость и скорость работы и качество кластеризации, что достигается использованием глобального критерия оптимизации на основе максимизации градиента высоты гистограммы кластера. Отличается простотой программной реализации. &lt;br /&gt;
&lt;br /&gt;
Во время работы алгоритм хранит в памяти небольшое количество информации по каждому кластеру и требует минимальное число сканирований набора данных. CLOPE автоматически подбирает количество кластеров, причем это регулируется одним единственным параметром - коэффициентом отталкивания &amp;lt;math&amp;gt; r &amp;lt;/math&amp;gt;. При этом он обеспечивает более высокую производительность и лучшее качество кластеризации в сравнении с многими иерархическими алгоритмами.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
Пусть имеется база транзакций &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, состоящая из множества транзакций &amp;lt;math&amp;gt;\{t_1,t_2,...,t_n\}&amp;lt;/math&amp;gt;. Каждая транзакция есть набор объектов &amp;lt;math&amp;gt;\{i_1,...,i_m\}&amp;lt;/math&amp;gt;. Множество кластеров &amp;lt;math&amp;gt;\{C_1,...,C_k\}&amp;lt;/math&amp;gt; есть разбиение множества &amp;lt;math&amp;gt;\{t_1,...,t_n\}&amp;lt;/math&amp;gt;, такое, что &amp;lt;math&amp;gt;C_1 \cup \dots \cup C_k=\{t_1,...,t_n\}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_i \ne \empty&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_i \cap C_j = \empty &amp;lt;/math&amp;gt;, для &amp;lt;math&amp;gt;i \ge 1, k \ge j&amp;lt;/math&amp;gt;. Каждый элемент &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; называется кластером, а &amp;lt;math&amp;gt;n, m, k&amp;lt;/math&amp;gt; – количество транзакций, количество объектов в базе транзакций и число кластеров соответственно.&lt;br /&gt;
&lt;br /&gt;
Каждый кластер &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; имеет следующие характеристики:&lt;br /&gt;
&amp;lt;math&amp;gt;D(C)&amp;lt;/math&amp;gt; – множество уникальных объектов;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;Occ(i,C)&amp;lt;/math&amp;gt; – количество вхождений (частота) объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; в кластер &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;S(C)= \sum_{i \in D(C)} Occ(i,C)= \sum_{t_i \in C}  \mid t_i  \mid , &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;W(C)=  \mid D(C) \mid ,H(C)=S(C)/W(C) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Функция стоимости:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; Profit(C) = \frac{\sum^{k}_{i=1} G(C_i) \times \mid C_i \mid} {\sum^{k}_{i=1} \mid C_i \mid } = \frac{\sum^{k}_{i=1} \frac{S(C_i)}{W(C_i)^r} \times \mid C_i \mid} {\sum^{k}_{i=1} \mid C_i \mid }  &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;\mid C_i \mid&amp;lt;/math&amp;gt;  количество объектов в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом кластере, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; – количество кластеров, &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; – коэффициент отталкивания &amp;lt;math&amp;gt;(0 &amp;lt; r \le 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С помощью параметра &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; регулируется уровень сходства транзакций внутри кластера, и, как&lt;br /&gt;
следствие, финальное количество кластеров. Этот коэффициент подбирается пользователем. Чем больше &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt;, тем ниже уровень сходства и тем больше кластеров будет сгенерировано.&lt;br /&gt;
&lt;br /&gt;
Постановка задачи кластеризации алгоритмом CLOPE выглядит следующим образом: &lt;br /&gt;
&lt;br /&gt;
для заданных &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; найти разбиение &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; такое, что: &lt;br /&gt;
&amp;lt;math&amp;gt;Profit(C) \longrightarrow max &amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит в вычислении на каждой итерации стоимости добавления и удаления транзакции из кластера: &lt;br /&gt;
&lt;br /&gt;
*вычисление нового размера кластера &amp;lt;math&amp;gt;S_{new}(C_i)=S(C_i) \pm \mid(t_n)\mid &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\mid(t_n)\mid&amp;lt;/math&amp;gt; - длина транзакции&lt;br /&gt;
&lt;br /&gt;
*вычисление новой ширины кластера &amp;lt;math&amp;gt;W_{new}(C_i)=\mid D(C_i \cup t_n)|&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*вычисление стоимости &amp;lt;math&amp;gt;\frac{S_{new}(C_i)(\mid C_i \mid \pm 1)}{W_{new}(C_i)^r} - \frac{S(C_i) \mid C_i \mid }{W(C_i)^r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм состоит из следующих этапов:&lt;br /&gt;
&lt;br /&gt;
1. &#039;&#039;&#039;Инициализация&#039;&#039;&#039;. На этом этапе происходит первый проход по таблице с транзакциями для построения начального разбиения, для каждой транзакции определяется кластер исходя из максимизации стоимости.&lt;br /&gt;
&lt;br /&gt;
2. &#039;&#039;&#039;Итерация&#039;&#039;&#039;. На данном этапе для каждой транзакции проводится попытка перемещения в другой кластер для максимизации функции стоимости.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
[[File:InitIter.PNG||500px]]&lt;br /&gt;
&lt;br /&gt;
Первая часть алгоритма - инициализация: для каждой транзакции вычисляется кластер, к которому она будет отнесена исходя из максимизации функции стоимости. Для этого вычисляется вспомогательная функция DeltaAdd, которая считает стоимость добавления транзакции к одному из существующих кластеров, либо к пустому. В итоге транзакция помещается в кластер, для которого цена добавления максимальна.&lt;br /&gt;
&lt;br /&gt;
Вторая часть алгоритма - уточняющие итерации: здесь происходит попытка улучшить вычисленные на первом этапе кластеры. В каждой итерации происходит перебор всех транзакций, и для каждой транзакции вычисляется цена удаления ее из текущего кластера и цена добавления в другой кластер. Суммарная стоимость перемещения будет являться суммой стоимостей удаления и добавления. Если максимальная стоимость перемещения данной транзакции в какой-либо больше нуля, то она перемещается в этот кластер. &lt;br /&gt;
&lt;br /&gt;
Вычисления происходят до тех пор, пока за итерацию происходит хотя бы одно перемещение транзакции. Если за итерацию не было произведено ни одного перемещения, то текущее состояние кластеров является устойчивым и оптимальным. &amp;lt;ref&amp;gt;Павлин Н. Кластеризация категорийных данных: масштабируемый алгоритм CLOPE, https://basegroup.ru/community/articles/clope&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Схема реализации на псевдокоде:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Входные параметры:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - транзакции&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; - коэффициент отталкивания&lt;br /&gt;
&lt;br /&gt;
Выходной параметр:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; кластеры, в начале алгоритма - пустое множество&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация:&#039;&#039;&#039;&lt;br /&gt;
    &#039;&#039;&#039;for&#039;&#039;&#039; t_i in t:&lt;br /&gt;
    max = 0&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; C_j in C:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; DeltaAdd(C_j,t_i,r) &amp;gt; max:&lt;br /&gt;
                max = DeltaAdd(C_j,t_i,r)&lt;br /&gt;
                C_best = C_j&lt;br /&gt;
    &#039;&#039;&#039;put&#039;&#039;&#039; t_i in C_best&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Итерации:&#039;&#039;&#039;&lt;br /&gt;
    move = True&lt;br /&gt;
    &#039;&#039;&#039;while&#039;&#039;&#039; move == True:&lt;br /&gt;
    move = False&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; t_i in t:&lt;br /&gt;
            max = 0&lt;br /&gt;
            C_now = t_i.cluster&lt;br /&gt;
            removeCost = DeltaRemove(C_now,t_i,r)&lt;br /&gt;
            &#039;&#039;&#039;for&#039;&#039;&#039; C_j in C:&lt;br /&gt;
                &#039;&#039;&#039;if&#039;&#039;&#039; DeltaAdd(C_j,t_i,r) + removeCost &amp;gt; max:&lt;br /&gt;
                    max = DeltaAdd(C_j,t_i,r) + removeCost&lt;br /&gt;
                    C_best = C_j&lt;br /&gt;
        if max &amp;gt; 0&lt;br /&gt;
            &#039;&#039;&#039;del&#039;&#039;&#039; t_i from C_now&lt;br /&gt;
            &#039;&#039;&#039;put&#039;&#039;&#039; t_i in C_best&lt;br /&gt;
            move = True&lt;br /&gt;
&lt;br /&gt;
Вспомогательная функция &#039;&#039;&#039;DeltaAdd&#039;&#039;&#039;:&lt;br /&gt;
    &#039;&#039;&#039;function&#039;&#039;&#039; DeltaAdd(C,t,r)&lt;br /&gt;
        S_new=C.size + t.itemCount&lt;br /&gt;
        W_new=C.wigth&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; item in t_i:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; C_j.occ(item) = 0&lt;br /&gt;
                &#039;&#039;W_new = W_new + 1&lt;br /&gt;
        &#039;&#039;&#039;return&#039;&#039;&#039; S_new * (C.count+1) / (W_new ^ r) - (C.size * C.count) / (C.wigth ^ r)&lt;br /&gt;
&lt;br /&gt;
Вспомогательная функция &#039;&#039;&#039;DeltaRemove&#039;&#039;&#039;:&lt;br /&gt;
    &#039;&#039;&#039;function&#039;&#039;&#039; DeltaRemove(C,t,r)&lt;br /&gt;
        S_new=C.size - t.itemCount&lt;br /&gt;
        W_new=C.wigth&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; item in t:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; C_j.occ(item) = 1&lt;br /&gt;
                &#039;&#039;W_new = W_new - 1&lt;br /&gt;
        &#039;&#039;&#039;return&#039;&#039;&#039; S_new * (C.count-1) / (W_new ^ r) - (C.size * C.count) / (C.wigth ^ r)&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
В соответствии с ранее введенным обозначением &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - количество транзакций, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина транзакции(максимальная), &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество кластеров.&lt;br /&gt;
&lt;br /&gt;
Основные вычисления восполняются в функции DeltaAdd/DeltaRemove: производится 1 сложение, не более &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; сложений/вычитаний, 2 умножения, 2 деления, 2 возведения в степень и 1 сложение - итого &amp;lt;math&amp;gt;m + 8&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;k&amp;lt;/math&amp;gt; штук). Итого выполняется &amp;lt;math&amp;gt;n*k*(m+8)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
В добавок к этому при добавлении/удалении транзакции к кластеру производится пересчет его характеристик: &amp;lt;math&amp;gt;m+2&amp;lt;/math&amp;gt; операции.&lt;br /&gt;
&lt;br /&gt;
Из того можно сделать вывод, что оценка сложность алгоритма равна &amp;lt;math&amp;gt;O(n*k*m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
&lt;br /&gt;
На рисунке ниже представлена схема этапа инициализации на примере входной транзакции &#039;&#039;&#039;T&#039;&#039;&#039; и четырех кластеров &#039;&#039;&#039;Cl 1&#039;&#039;&#039;, &#039;&#039;&#039;Cl 2&#039;&#039;&#039;, &#039;&#039;&#039;Cl 3&#039;&#039;&#039; и &#039;&#039;&#039;Cl 4&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Объект &#039;&#039;&#039;DeltaAdd&#039;&#039;&#039; соответствует выполнению соответствующей функции для вычисления цены добавления транзакции на кластер. После выполнения всех &#039;&#039;&#039;DeltaAdd&#039;&#039;&#039; для одной транзакции выполняется определение максимального значения функции и выбор кластера, на который будет помещена транзакция. На этапе инициализации при обработке каждой транзакции количество кластеров может как увеличиться, так и остаться неизменным.&lt;br /&gt;
&lt;br /&gt;
[[File:InitDef.PNG||700px]]&lt;br /&gt;
&lt;br /&gt;
Этап итераций отличается только тем, что на нем дополнительно считается функция &#039;&#039;&#039;DeltaRemove&#039;&#039;&#039; вычисления стоимости удаления транзакции с кластера. На этапе итерации функции DeltaAdd/DeltaRemove могут считать параллельно для каждой транзакции.&lt;br /&gt;
&lt;br /&gt;
Синие точки сетки - вычисление функций DeltaAdd. На этапе инициализации количество кластеров может как увеличиться, так и не измениться, это показано пунктирными линиями.&lt;br /&gt;
[[File:init1.PNG|thumb|center|300px|Этап Инициализации]]&lt;br /&gt;
&lt;br /&gt;
Зеленые точки сетки - вычисление функций DeltaAdd и DeltaRemove. На этапе итераций функции могут считаться параллельно для каждой транзакции.&lt;br /&gt;
[[File:iter1.PNG|thumb|center|300px|Этап Итераций]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Вычисление стоимости добавления/удаления транзакции, которые выполняются функциями DeltaAdd/DeltaRemove, происходит независимо для всех &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; кластеров. Поэтому все вычисления можно производить параллельно. Таким образом сложность алгоритма с &amp;lt;math&amp;gt;O(n*k*m)&amp;lt;/math&amp;gt; понижается до &amp;lt;math&amp;gt;O(n*m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; транзакций длины &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; и коэффициент отталкивания &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
метки классов для каждой транзакции в соответствии с проведенной кластеризацией(числовая последовательность длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной сложности алгоритма определяется количеством кластеров: &amp;lt;math&amp;gt;\dfrac{O(n*k*m)}{O(n*m)} = k&amp;lt;/math&amp;gt;&lt;br /&gt;
* [[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]] алгоритма равна &amp;lt;math&amp;gt;\dfrac{nk(m+8) + m + 2}{nm + n + 1} \cong k&amp;lt;/math&amp;gt;&lt;br /&gt;
* Алгоритм не является [[глоссарий#Устойчивость|&#039;&#039;устойчивым&#039;&#039;]], так как результат работы зависит от порядка чтения транзакций и от текущего набора транзакций в кластере.&lt;br /&gt;
* Выполняется свойство сбалансированности операций между параллельными ветвями алгоритма, так как для каждой транзакции выполняются функции DeltaAdd/DeltaRemove, считающие стоимость добавления/удаления транзакции.&lt;br /&gt;
* Свойство [[глоссарий#Детерминированность|&#039;&#039;детерминированности алгоритмов&#039;&#039;]] не выполняется, так как результат алгоритма зависит от порядка прохождения транзакций. Но если рассматривать транзакции как нумерованный список, то результат будет определен однозначно от запуска к запуску. Однако существует расширение алгоритма, обеспечивающее свойство детерминированности. &amp;lt;ref&amp;gt;Li, Y., Le, J., Wang, M. Improving CLOPE’s Profit Value and Stability with an Optimized Agglomerative Approach. Algorithms 2015, 8, 380-394.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
* Так как алгоритм предназначен для кластеризации категориальных данных, то он практически неприменим для числовой кластеризации.&lt;br /&gt;
* Быстро работает даже для большого количества данных, обеспечивая при этом хорошее качество кластеризации&lt;br /&gt;
* Имеет простую реализацию&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
Проверка масштабируемости проводилась на суперкомпьютере &amp;quot;Ломоносов&amp;quot; с использованием компилятора Intel(13.1.0) и стандарта OpenMP для 1000, 2000, 3000, 4000 и 5000 транзакций из пяти латинских букв с использованием 1, 2, 4, 8 и 16 нитей. Использованные параметры компиляции и запуска:&lt;br /&gt;
&lt;br /&gt;
    icc -openmp CLOPE.cpp -o clope&lt;br /&gt;
    &lt;br /&gt;
    export OMP_NUM_THREADS = k (k - число нитей)&lt;br /&gt;
    sbatch -p test -N 1 run ./clope tr 5 3 (tr - количество транзакций)&lt;br /&gt;
&lt;br /&gt;
Используемая реализация:&lt;br /&gt;
&lt;br /&gt;
    #include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
    #include &amp;lt;cstdlib&amp;gt;&lt;br /&gt;
    #include &amp;lt;cmath&amp;gt;&lt;br /&gt;
    #include &amp;lt;cstring&amp;gt;&lt;br /&gt;
    #include &amp;lt;set&amp;gt;&lt;br /&gt;
    #include &amp;lt;vector&amp;gt;&lt;br /&gt;
    #include &amp;quot;omp.h&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    using namespace std;&lt;br /&gt;
    &lt;br /&gt;
    double r = 1.6;&lt;br /&gt;
    int t_num = 5000;&lt;br /&gt;
    int t_len = 5;&lt;br /&gt;
    &lt;br /&gt;
    struct Clust&lt;br /&gt;
    {&lt;br /&gt;
      int size;&lt;br /&gt;
      int count;&lt;br /&gt;
      int width;&lt;br /&gt;
      multiset &amp;lt;char&amp;gt; clus;&lt;br /&gt;
      Clust(){&lt;br /&gt;
          size = 0;&lt;br /&gt;
          count = 0;&lt;br /&gt;
          width = 0;}&lt;br /&gt;
    };&lt;br /&gt;
    &lt;br /&gt;
    void AddTransaction(Clust &amp;amp;C, char* t)&lt;br /&gt;
    {&lt;br /&gt;
      C.size = C.size + t_len;&lt;br /&gt;
      C.count = C.count + 1;&lt;br /&gt;
    &lt;br /&gt;
      for (int i = 0; i &amp;lt; t_len; i++){&lt;br /&gt;
        if (C.clus.count(t[i]) == 0) {&lt;br /&gt;
          C.width = C.width + 1;&lt;br /&gt;
        }&lt;br /&gt;
        C.clus.insert(t[i]);&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    void RemoveTransaction(Clust &amp;amp;C, char* t)&lt;br /&gt;
    {&lt;br /&gt;
      C.size = C.size - t_len;&lt;br /&gt;
      C.count = C.count - 1;&lt;br /&gt;
    &lt;br /&gt;
      for (int i = 0; i &amp;lt; t_len; i++){&lt;br /&gt;
        if (C.clus.count(t[i]) == 1) {&lt;br /&gt;
          C.width = C.width - 1;&lt;br /&gt;
        }&lt;br /&gt;
        C.clus.erase(C.clus.find(t[i]));&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    double AddCost(Clust C, char* t)&lt;br /&gt;
    {&lt;br /&gt;
      int S = C.size;&lt;br /&gt;
      int N = C.count;&lt;br /&gt;
      int W = C.width;&lt;br /&gt;
      int Snew = S + t_len;&lt;br /&gt;
      int Nnew = N + 1;&lt;br /&gt;
      int Wnew = W;&lt;br /&gt;
      set &amp;lt;int&amp;gt; tmp;&lt;br /&gt;
    &lt;br /&gt;
      for (int i = 0; i &amp;lt; t_len; i++){&lt;br /&gt;
        if (C.clus.count(t[i]) == 0 &amp;amp;&amp;amp; tmp.count(t[i]) == 0) {&lt;br /&gt;
          Wnew = Wnew + 1;&lt;br /&gt;
        }&lt;br /&gt;
        tmp.insert(t[i]);&lt;br /&gt;
      }&lt;br /&gt;
      return (Snew * Nnew) / (pow(Wnew, r)) - ((S == 0) ? 0 : (S * N) / (pow(W, r)));&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    double RemoveCost(Clust C, char* t)&lt;br /&gt;
    {&lt;br /&gt;
      int S = C.size;&lt;br /&gt;
      int N = C.count;&lt;br /&gt;
      int W = C.width;&lt;br /&gt;
      int Snew = S - t_len;&lt;br /&gt;
      int Nnew = N - 1;&lt;br /&gt;
      int Wnew = W;&lt;br /&gt;
    &lt;br /&gt;
      for (int i = 0; i &amp;lt; t_len; i++){&lt;br /&gt;
        if (C.clus.count(t[i]) == 1) {&lt;br /&gt;
          Wnew = Wnew - 1;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      return ((Wnew == 0) ? 0 : (Snew * Nnew) / (pow(Wnew, r))) - (S * N) / (pow(W, r));&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    int main(int argc, char **argv)&lt;br /&gt;
    {&lt;br /&gt;
      int ClusCnt = 0;&lt;br /&gt;
      double maxCost;&lt;br /&gt;
      int bestChoice;&lt;br /&gt;
      double remCost;&lt;br /&gt;
        int i, j, k;&lt;br /&gt;
        int tr = omp_get_max_threads();&lt;br /&gt;
        bool moved = false;&lt;br /&gt;
    &lt;br /&gt;
    t_num = atoi(argv[1]);&lt;br /&gt;
    t_len = atoi(argv[2]);&lt;br /&gt;
    r = atof(argv[3]);&lt;br /&gt;
    &lt;br /&gt;
      int* Distr = (int*)malloc(t_num * sizeof(int));&lt;br /&gt;
    &lt;br /&gt;
      char** T = (char **)malloc(t_num * sizeof(char*));&lt;br /&gt;
      T[0] = (char *)malloc(t_num * t_len * sizeof(char));&lt;br /&gt;
      for (i=1; i &amp;lt; t_num; i++){&lt;br /&gt;
        T[i] = T[i-1] + t_len;&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
        vector&amp;lt;Clust&amp;gt; C;&lt;br /&gt;
        C.push_back(Clust());&lt;br /&gt;
    &lt;br /&gt;
      FILE* input = fopen(&amp;quot;input.txt&amp;quot;, &amp;quot;r&amp;quot;);&lt;br /&gt;
          for (i = 0; i &amp;lt; t_num; i++) {&lt;br /&gt;
            for (j = 0; j &amp;lt; t_len; j++) {&lt;br /&gt;
              fscanf(input, &amp;quot;%c &amp;quot;, &amp;amp;T[i][j]);&lt;br /&gt;
            }&lt;br /&gt;
          }&lt;br /&gt;
    &lt;br /&gt;
    //Инициализация&lt;br /&gt;
    &lt;br /&gt;
      double tm = omp_get_wtime();&lt;br /&gt;
      AddTransaction(C[0], T[0]);&lt;br /&gt;
      ClusCnt++;&lt;br /&gt;
      C.push_back(Clust());&lt;br /&gt;
    &lt;br /&gt;
        Distr[0] = 0;&lt;br /&gt;
    &lt;br /&gt;
      for (i = 1; i &amp;lt; t_num; i++){&lt;br /&gt;
        maxCost = 0;&lt;br /&gt;
        double add[ClusCnt + 1];&lt;br /&gt;
    &lt;br /&gt;
        #pragma omp parallel for private(j) shared(ClusCnt, add, C, T)&lt;br /&gt;
        for (j = 0; j &amp;lt;= ClusCnt; j++){&lt;br /&gt;
          add[j] = AddCost(C[j], T[i]);&lt;br /&gt;
        }&lt;br /&gt;
    &lt;br /&gt;
          for (j = 0; j &amp;lt;= ClusCnt; j++){&lt;br /&gt;
          if (add[j] &amp;gt; maxCost){&lt;br /&gt;
            maxCost = add[j];&lt;br /&gt;
            bestChoice = j;&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
        if (bestChoice == ClusCnt){&lt;br /&gt;
          ClusCnt++;&lt;br /&gt;
          C.push_back(Clust());&lt;br /&gt;
        }&lt;br /&gt;
        AddTransaction(C[bestChoice], T[i]);&lt;br /&gt;
        Distr[i] = bestChoice;&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
    //Итерации&lt;br /&gt;
      for (k = 0; k &amp;lt; 10; k++){ // k - число итераций&lt;br /&gt;
          moved = false;&lt;br /&gt;
          double add[ClusCnt + 1];&lt;br /&gt;
    &lt;br /&gt;
          for (i = 0; i &amp;lt; t_num; i++){&lt;br /&gt;
           maxCost = 0;&lt;br /&gt;
           remCost = RemoveCost(C[Distr[i]],T[i]);&lt;br /&gt;
    &lt;br /&gt;
           #pragma omp parallel for private(j) shared(ClusCnt, add, C, T, Distr, remCost)&lt;br /&gt;
           for (j = 0; j &amp;lt;= ClusCnt; j++){&lt;br /&gt;
            if (j != Distr[i]) {&lt;br /&gt;
              add[j] = AddCost(C[j], T[i]) + remCost;&lt;br /&gt;
              }&lt;br /&gt;
           }&lt;br /&gt;
            for (j = 0; j &amp;lt;= ClusCnt; j++){&lt;br /&gt;
              if (j != Distr[i]){&lt;br /&gt;
              if (add[j] &amp;gt; maxCost) {&lt;br /&gt;
                maxCost = add[j];&lt;br /&gt;
                bestChoice = j;&lt;br /&gt;
                }&lt;br /&gt;
              }&lt;br /&gt;
            }&lt;br /&gt;
    &lt;br /&gt;
            if (maxCost &amp;gt; 0){&lt;br /&gt;
              if (bestChoice == ClusCnt){&lt;br /&gt;
                ClusCnt++;&lt;br /&gt;
                C.push_back(Clust());&lt;br /&gt;
              }&lt;br /&gt;
              RemoveTransaction(C[Distr[i]], T[i]);&lt;br /&gt;
              AddTransaction(C[bestChoice], T[i]);&lt;br /&gt;
              Distr[i] = bestChoice;&lt;br /&gt;
              moved = true;&lt;br /&gt;
            }&lt;br /&gt;
          }&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
    tm = omp_get_wtime() - tm;&lt;br /&gt;
    &lt;br /&gt;
    printf(&amp;quot;size:%d\twidth:%d\tcl_cnt:%d\threads:%d\ttime:%lf seconds\tr:%lf&amp;quot;,t_num,t_len,ClusCnt - 1,tr,tm,r);&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    FILE* output = fopen(&amp;quot;out.txt&amp;quot;,&amp;quot;w&amp;quot;);&lt;br /&gt;
    for (int j = 0; j &amp;lt;= ClusCnt; j++){&lt;br /&gt;
        fprintf(output,&amp;quot;Cluster %d:\n&amp;quot;,j);&lt;br /&gt;
        for (multiset&amp;lt;char&amp;gt;::iterator it = C[j].clus.begin(); it != C[j].clus.end(); it++){&lt;br /&gt;
                fprintf(output,&amp;quot;%c&amp;quot;,*it);&lt;br /&gt;
        }&lt;br /&gt;
        fprintf(output,&amp;quot;\n&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    fclose(input);&lt;br /&gt;
    fclose(output);&lt;br /&gt;
    free(T[0]);&lt;br /&gt;
    free(T);&lt;br /&gt;
    free(Distr);&lt;br /&gt;
    &lt;br /&gt;
    return 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
Результаты проверки на графике ниже.&lt;br /&gt;
&lt;br /&gt;
[[file:Clope lom.PNG|thumb|center|1000px]]&lt;br /&gt;
&lt;br /&gt;
В данной реализации алгоритм показал плохую масштабируемость. Оптимальное число нитей - 8.&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
* http://weka.sourceforge.net/doc.stable/weka/clusterers/CLOPE.html - реализация в open source библиотеке для анализа данных WEKA(Waikato Environment for Knowledge Analysis) на языке Java&lt;br /&gt;
Также существуют пользовательские реализации алгоритма:&lt;br /&gt;
* https://github.com/infozor/php_mysql_clustering_clope - реализация алгоритма на PHP&lt;br /&gt;
* https://github.com/Tolsi/scala-clope - реализация алгоритма Scala&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:%D0%9F%D0%B0%D0%B2%D0%B5%D0%BB/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BA%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D0%B9%D0%BD%D1%8B%D1%85_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85_CLOPE&amp;diff=22501</id>
		<title>Участник:Павел/Алгоритм кластеризации категорийных данных CLOPE</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9F%D0%B0%D0%B2%D0%B5%D0%BB/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BA%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D0%B9%D0%BD%D1%8B%D1%85_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85_CLOPE&amp;diff=22501"/>
		<updated>2017-02-15T08:01:17Z</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;
Алгоритм CLOPE (Clustering with sLOPE&amp;lt;ref&amp;gt;Yang, Y., Guan, H., You. J. CLOPE: A fast and Effective Clustering Algorithm for Transactional Data In Proc. of SIGKDD’02, July 23-26, 2002, Edmonton, Alberta, Canada.&amp;lt;/ref&amp;gt;) неирархический метод кластеризации, предназначенный для кластеризации огромных наборов категорийных данных. К достоинствам алгоритма относятся высокие масштабируемость и скорость работы и качество кластеризации, что достигается использованием глобального критерия оптимизации на основе максимизации градиента высоты гистограммы кластера. Отличается простотой программной реализации. &lt;br /&gt;
&lt;br /&gt;
Во время работы алгоритм хранит в памяти небольшое количество информации по каждому кластеру и требует минимальное число сканирований набора данных. CLOPE автоматически подбирает количество кластеров, причем это регулируется одним единственным параметром - коэффициентом отталкивания &amp;lt;math&amp;gt; r &amp;lt;/math&amp;gt;. При этом он обеспечивает более высокую производительность и лучшее качество кластеризации в сравнении с многими иерархическими алгоритмами.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
Пусть имеется база транзакций &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, состоящая из множества транзакций &amp;lt;math&amp;gt;\{t_1,t_2,...,t_n\}&amp;lt;/math&amp;gt;. Каждая транзакция есть набор объектов &amp;lt;math&amp;gt;\{i_1,...,i_m\}&amp;lt;/math&amp;gt;. Множество кластеров &amp;lt;math&amp;gt;\{C_1,...,C_k\}&amp;lt;/math&amp;gt; есть разбиение множества &amp;lt;math&amp;gt;\{t_1,...,t_n\}&amp;lt;/math&amp;gt;, такое, что &amp;lt;math&amp;gt;C_1 \cup \dots \cup C_k=\{t_1,...,t_n\}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_i \ne \empty&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_i \cap C_j = \empty &amp;lt;/math&amp;gt;, для &amp;lt;math&amp;gt;i \ge 1, k \ge j&amp;lt;/math&amp;gt;. Каждый элемент &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; называется кластером, а &amp;lt;math&amp;gt;n, m, k&amp;lt;/math&amp;gt; – количество транзакций, количество объектов в базе транзакций и число кластеров соответственно.&lt;br /&gt;
&lt;br /&gt;
Каждый кластер &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; имеет следующие характеристики:&lt;br /&gt;
&amp;lt;math&amp;gt;D(C)&amp;lt;/math&amp;gt; – множество уникальных объектов;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;Occ(i,C)&amp;lt;/math&amp;gt; – количество вхождений (частота) объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; в кластер &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;S(C)= \sum_{i \in D(C)} Occ(i,C)= \sum_{t_i \in C}  \mid t_i  \mid , &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;W(C)=  \mid D(C) \mid ,H(C)=S(C)/W(C) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Функция стоимости:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; Profit(C) = \frac{\sum^{k}_{i=1} G(C_i) \times \mid C_i \mid} {\sum^{k}_{i=1} \mid C_i \mid } = \frac{\sum^{k}_{i=1} \frac{S(C_i)}{W(C_i)^r} \times \mid C_i \mid} {\sum^{k}_{i=1} \mid C_i \mid }  &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;\mid C_i \mid&amp;lt;/math&amp;gt;  количество объектов в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом кластере, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; – количество кластеров, &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; – коэффициент отталкивания &amp;lt;math&amp;gt;(0 &amp;lt; r \le 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С помощью параметра &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; регулируется уровень сходства транзакций внутри кластера, и, как&lt;br /&gt;
следствие, финальное количество кластеров. Этот коэффициент подбирается пользователем. Чем больше &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt;, тем ниже уровень сходства и тем больше кластеров будет сгенерировано.&lt;br /&gt;
&lt;br /&gt;
Постановка задачи кластеризации алгоритмом CLOPE выглядит следующим образом: &lt;br /&gt;
&lt;br /&gt;
для заданных &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; найти разбиение &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; такое, что: &lt;br /&gt;
&amp;lt;math&amp;gt;Profit(C) \longrightarrow max &amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит в вычислении на каждой итерации стоимости добавления и удаления транзакции из кластера: &lt;br /&gt;
&lt;br /&gt;
*вычисление нового размера кластера &amp;lt;math&amp;gt;S_{new}(C_i)=S(C_i) \pm \mid(t_n)\mid &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\mid(t_n)\mid&amp;lt;/math&amp;gt; - длина транзакции&lt;br /&gt;
&lt;br /&gt;
*вычисление новой ширины кластера &amp;lt;math&amp;gt;W_{new}(C_i)=\mid D(C_i \cup t_n)|&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*вычисление стоимости &amp;lt;math&amp;gt;\frac{S_{new}(C_i)(\mid C_i \mid \pm 1)}{W_{new}(C_i)^r} - \frac{S(C_i) \mid C_i \mid }{W(C_i)^r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм состоит из следующих этапов:&lt;br /&gt;
&lt;br /&gt;
1. &#039;&#039;&#039;Инициализация&#039;&#039;&#039;. На этом этапе происходит первый проход по таблице с транзакциями для построения начального разбиения, для каждой транзакции определяется кластер исходя из максимизации стоимости.&lt;br /&gt;
&lt;br /&gt;
2. &#039;&#039;&#039;Итерация&#039;&#039;&#039;. На данном этапе для каждой транзакции проводится попытка перемещения в другой кластер для максимизации функции стоимости.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
[[File:InitIter.PNG||500px]]&lt;br /&gt;
&lt;br /&gt;
Первая часть алгоритма - инициализация: для каждой транзакции вычисляется кластер, к которому она будет отнесена исходя из максимизации функции стоимости. Для этого вычисляется вспомогательная функция DeltaAdd, которая считает стоимость добавления транзакции к одному из существующих кластеров, либо к пустому. В итоге транзакция помещается в кластер, для которого цена добавления максимальна.&lt;br /&gt;
&lt;br /&gt;
Вторая часть алгоритма - уточняющие итерации: здесь происходит попытка улучшить вычисленные на первом этапе кластеры. В каждой итерации происходит перебор всех транзакций, и для каждой транзакции вычисляется цена удаления ее из текущего кластера и цена добавления в другой кластер. Суммарная стоимость перемещения будет являться суммой стоимостей удаления и добавления. Если максимальная стоимость перемещения данной транзакции в какой-либо больше нуля, то она перемещается в этот кластер. &lt;br /&gt;
&lt;br /&gt;
Вычисления происходят до тех пор, пока за итерацию происходит хотя бы одно перемещение транзакции. Если за итерацию не было произведено ни одного перемещения, то текущее состояние кластеров является устойчивым и оптимальным. &amp;lt;ref&amp;gt;Павлин Н. Кластеризация категорийных данных: масштабируемый алгоритм CLOPE, https://basegroup.ru/community/articles/clope&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Схема реализации на псевдокоде:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Входные параметры:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - транзакции&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; - коэффициент отталкивания&lt;br /&gt;
&lt;br /&gt;
Выходной параметр:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; кластеры, в начале алгоритма - пустое множество&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация:&#039;&#039;&#039;&lt;br /&gt;
    &#039;&#039;&#039;for&#039;&#039;&#039; t_i in t:&lt;br /&gt;
    max = 0&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; C_j in C:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; DeltaAdd(C_j,t_i,r) &amp;gt; max:&lt;br /&gt;
                max = DeltaAdd(C_j,t_i,r)&lt;br /&gt;
                C_best = C_j&lt;br /&gt;
    &#039;&#039;&#039;put&#039;&#039;&#039; t_i in C_best&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Итерации:&#039;&#039;&#039;&lt;br /&gt;
    move = True&lt;br /&gt;
    &#039;&#039;&#039;while&#039;&#039;&#039; move == True:&lt;br /&gt;
    move = False&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; t_i in t:&lt;br /&gt;
            max = 0&lt;br /&gt;
            C_now = t_i.cluster&lt;br /&gt;
            removeCost = DeltaRemove(C_now,t_i,r)&lt;br /&gt;
            &#039;&#039;&#039;for&#039;&#039;&#039; C_j in C:&lt;br /&gt;
                &#039;&#039;&#039;if&#039;&#039;&#039; DeltaAdd(C_j,t_i,r) + removeCost &amp;gt; max:&lt;br /&gt;
                    max = DeltaAdd(C_j,t_i,r) + removeCost&lt;br /&gt;
                    C_best = C_j&lt;br /&gt;
        if max &amp;gt; 0&lt;br /&gt;
            &#039;&#039;&#039;del&#039;&#039;&#039; t_i from C_now&lt;br /&gt;
            &#039;&#039;&#039;put&#039;&#039;&#039; t_i in C_best&lt;br /&gt;
            move = True&lt;br /&gt;
&lt;br /&gt;
Вспомогательная функция &#039;&#039;&#039;DeltaAdd&#039;&#039;&#039;:&lt;br /&gt;
    &#039;&#039;&#039;function&#039;&#039;&#039; DeltaAdd(C,t,r)&lt;br /&gt;
        S_new=C.size + t.itemCount&lt;br /&gt;
        W_new=C.wigth&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; item in t_i:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; C_j.occ(item) = 0&lt;br /&gt;
                &#039;&#039;W_new = W_new + 1&lt;br /&gt;
        &#039;&#039;&#039;return&#039;&#039;&#039; S_new * (C.count+1) / (W_new ^ r) - (C.size * C.count) / (C.wigth ^ r)&lt;br /&gt;
&lt;br /&gt;
Вспомогательная функция &#039;&#039;&#039;DeltaRemove&#039;&#039;&#039;:&lt;br /&gt;
    &#039;&#039;&#039;function&#039;&#039;&#039; DeltaRemove(C,t,r)&lt;br /&gt;
        S_new=C.size - t.itemCount&lt;br /&gt;
        W_new=C.wigth&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; item in t:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; C_j.occ(item) = 1&lt;br /&gt;
                &#039;&#039;W_new = W_new - 1&lt;br /&gt;
        &#039;&#039;&#039;return&#039;&#039;&#039; S_new * (C.count-1) / (W_new ^ r) - (C.size * C.count) / (C.wigth ^ r)&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
В соответствии с ранее введенным обозначением &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - количество транзакций, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина транзакции(максимальная), &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество кластеров.&lt;br /&gt;
&lt;br /&gt;
Основные вычисления восполняются в функции DeltaAdd/DeltaRemove: производится 1 сложение, не более &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; сложений/вычитаний, 2 умножения, 2 деления, 2 возведения в степень и 1 сложение - итого &amp;lt;math&amp;gt;m + 8&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;k&amp;lt;/math&amp;gt; штук). Итого выполняется &amp;lt;math&amp;gt;n*k*(m+8)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
В добавок к этому при добавлении/удалении транзакции к кластеру производится пересчет его характеристик: &amp;lt;math&amp;gt;m+2&amp;lt;/math&amp;gt; операции.&lt;br /&gt;
&lt;br /&gt;
Из того можно сделать вывод, что оценка сложность алгоритма равна &amp;lt;math&amp;gt;O(n*k*m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
&lt;br /&gt;
На рисунке ниже представлена схема этапа инициализации на примере входной транзакции &#039;&#039;&#039;T&#039;&#039;&#039; и четырех кластеров &#039;&#039;&#039;Cl 1&#039;&#039;&#039;, &#039;&#039;&#039;Cl 2&#039;&#039;&#039;, &#039;&#039;&#039;Cl 3&#039;&#039;&#039; и &#039;&#039;&#039;Cl 4&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Объект &#039;&#039;&#039;DeltaAdd&#039;&#039;&#039; соответствует выполнению соответствующей функции для вычисления цены добавления транзакции на кластер. После выполнения всех &#039;&#039;&#039;DeltaAdd&#039;&#039;&#039; для одной транзакции выполняется определение максимального значения функции и выбор кластера, на который будет помещена транзакция. На этапе инициализации при обработке каждой транзакции количество кластеров может как увеличиться, так и остаться неизменным.&lt;br /&gt;
&lt;br /&gt;
[[File:InitDef.PNG||700px]]&lt;br /&gt;
&lt;br /&gt;
Этап итераций отличается только тем, что на нем дополнительно считается функция &#039;&#039;&#039;DeltaRemove&#039;&#039;&#039; вычисления стоимости удаления транзакции с кластера. На этапе итерации функции DeltaAdd/DeltaRemove могут считать параллельно для каждой транзакции.&lt;br /&gt;
&lt;br /&gt;
Синие точки сетки - вычисление функций DeltaAdd. На этапе инициализации количество кластеров может как увеличиться, так и не измениться, это показано пунктирными линиями.&lt;br /&gt;
[[File:init1.PNG|thumb|center|300px|Этап Инициализации]]&lt;br /&gt;
&lt;br /&gt;
Зеленые точки сетки - вычисление функций DeltaAdd и DeltaRemove. На этапе итераций функции могут считаться параллельно для каждой транзакции.&lt;br /&gt;
[[File:iter1.PNG|thumb|center|300px|Этап Итераций]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Вычисление стоимости добавления/удаления транзакции, которые выполняются функциями DeltaAdd/DeltaRemove, происходит независимо для всех &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; кластеров. Поэтому все вычисления можно производить параллельно. Таким образом сложность алгоритма с &amp;lt;math&amp;gt;O(n*k*m)&amp;lt;/math&amp;gt; понижается до &amp;lt;math&amp;gt;O(n*m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; транзакций длины &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; и коэффициент отталкивания &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
метки классов для каждой транзакции в соответствии с проведенной кластеризацией(числовая последовательность длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной сложности алгоритма определяется количеством кластеров: &amp;lt;math&amp;gt;\dfrac{O(n*k*m)}{O(n*m)} = k&amp;lt;/math&amp;gt;&lt;br /&gt;
* [[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]] алгоритма равна &amp;lt;math&amp;gt;\dfrac{nk(m+8) + m + 2}{nm + n + 1} \cong k&amp;lt;/math&amp;gt;&lt;br /&gt;
* Алгоритм не является [[глоссарий#Устойчивость|&#039;&#039;устойчивым&#039;&#039;]], так как результат работы зависит от порядка чтения транзакций и от текущего набора транзакций в кластере.&lt;br /&gt;
* Выполняется свойство сбалансированности операций между параллельными ветвями алгоритма, так как для каждой транзакции выполняются функции DeltaAdd/DeltaRemove, считающие стоимость добавления/удаления транзакции.&lt;br /&gt;
* Свойство [[глоссарий#Детерминированность|&#039;&#039;детерминированности алгоритмов&#039;&#039;]] не выполняется, так как результат алгоритма зависит от порядка прохождения транзакций. Но если рассматривать транзакции как нумерованный список, то результат будет определен однозначно от запуска к запуску. Однако существует расширение алгоритма, обеспечивающее свойство детерминированности. &amp;lt;ref&amp;gt;Li, Y., Le, J., Wang, M. Improving CLOPE’s Profit Value and Stability with an Optimized Agglomerative Approach. Algorithms 2015, 8, 380-394.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
* Так как алгоритм предназначен для кластеризации категориальных данных, то он практически неприменим для числовой кластеризации.&lt;br /&gt;
* Быстро работает даже для большого количества данных, обеспечивая при этом хорошее качество кластеризации&lt;br /&gt;
* Имеет простую реализацию&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
Проверка масштабируемости проводилась на суперкомпьютере &amp;quot;Ломоносов&amp;quot; с использованием компилятора Intel(13.1.0) и стандарта OpenMP для 1000, 2000, 3000, 4000 и 5000 транзакций из пяти латинских букв с использованием 1, 2, 4, 8 и 16 нитей. Использованные параметры компиляции и запуска:&lt;br /&gt;
&lt;br /&gt;
    icc -openmp CLOPE.cpp -o clope&lt;br /&gt;
    &lt;br /&gt;
    export OMP_NUM_THREADS = k (k - число нитей)&lt;br /&gt;
    sbatch -p test -N 1 run ./clope tr 5 3 (tr - количество транзакций)&lt;br /&gt;
&lt;br /&gt;
Используемая реализация:&lt;br /&gt;
&lt;br /&gt;
    #include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
    #include &amp;lt;cstdlib&amp;gt;&lt;br /&gt;
    #include &amp;lt;cmath&amp;gt;&lt;br /&gt;
    #include &amp;lt;cstring&amp;gt;&lt;br /&gt;
    #include &amp;lt;set&amp;gt;&lt;br /&gt;
    #include &amp;lt;vector&amp;gt;&lt;br /&gt;
    #include &amp;quot;omp.h&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    using namespace std;&lt;br /&gt;
    &lt;br /&gt;
    double r = 1.6;&lt;br /&gt;
    int t_num = 5000;&lt;br /&gt;
    int t_len = 5;&lt;br /&gt;
    &lt;br /&gt;
    struct Clust&lt;br /&gt;
    {&lt;br /&gt;
      int size;&lt;br /&gt;
      int count;&lt;br /&gt;
      int width;&lt;br /&gt;
      multiset &amp;lt;char&amp;gt; clus;&lt;br /&gt;
      Clust(){&lt;br /&gt;
          size = 0;&lt;br /&gt;
          count = 0;&lt;br /&gt;
          width = 0;}&lt;br /&gt;
    };&lt;br /&gt;
    &lt;br /&gt;
    void AddTransaction(Clust &amp;amp;C, char* t)&lt;br /&gt;
    {&lt;br /&gt;
      C.size = C.size + t_len;&lt;br /&gt;
      C.count = C.count + 1;&lt;br /&gt;
    &lt;br /&gt;
      for (int i = 0; i &amp;lt; t_len; i++){&lt;br /&gt;
        if (C.clus.count(t[i]) == 0) {&lt;br /&gt;
          C.width = C.width + 1;&lt;br /&gt;
        }&lt;br /&gt;
        C.clus.insert(t[i]);&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    void RemoveTransaction(Clust &amp;amp;C, char* t)&lt;br /&gt;
    {&lt;br /&gt;
      C.size = C.size - t_len;&lt;br /&gt;
      C.count = C.count - 1;&lt;br /&gt;
    &lt;br /&gt;
      for (int i = 0; i &amp;lt; t_len; i++){&lt;br /&gt;
        if (C.clus.count(t[i]) == 1) {&lt;br /&gt;
          C.width = C.width - 1;&lt;br /&gt;
        }&lt;br /&gt;
        C.clus.erase(C.clus.find(t[i]));&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    double AddCost(Clust C, char* t)&lt;br /&gt;
    {&lt;br /&gt;
      int S = C.size;&lt;br /&gt;
      int N = C.count;&lt;br /&gt;
      int W = C.width;&lt;br /&gt;
      int Snew = S + t_len;&lt;br /&gt;
      int Nnew = N + 1;&lt;br /&gt;
      int Wnew = W;&lt;br /&gt;
      set &amp;lt;int&amp;gt; tmp;&lt;br /&gt;
    &lt;br /&gt;
      for (int i = 0; i &amp;lt; t_len; i++){&lt;br /&gt;
        if (C.clus.count(t[i]) == 0 &amp;amp;&amp;amp; tmp.count(t[i]) == 0) {&lt;br /&gt;
          Wnew = Wnew + 1;&lt;br /&gt;
        }&lt;br /&gt;
        tmp.insert(t[i]);&lt;br /&gt;
      }&lt;br /&gt;
      return (Snew * Nnew) / (pow(Wnew, r)) - ((S == 0) ? 0 : (S * N) / (pow(W, r)));&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    double RemoveCost(Clust C, char* t)&lt;br /&gt;
    {&lt;br /&gt;
      int S = C.size;&lt;br /&gt;
      int N = C.count;&lt;br /&gt;
      int W = C.width;&lt;br /&gt;
      int Snew = S - t_len;&lt;br /&gt;
      int Nnew = N - 1;&lt;br /&gt;
      int Wnew = W;&lt;br /&gt;
    &lt;br /&gt;
      for (int i = 0; i &amp;lt; t_len; i++){&lt;br /&gt;
        if (C.clus.count(t[i]) == 1) {&lt;br /&gt;
          Wnew = Wnew - 1;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      return ((Wnew == 0) ? 0 : (Snew * Nnew) / (pow(Wnew, r))) - (S * N) / (pow(W, r));&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    int main(int argc, char **argv)&lt;br /&gt;
    {&lt;br /&gt;
      int ClusCnt = 0;&lt;br /&gt;
      double maxCost;&lt;br /&gt;
      int bestChoice;&lt;br /&gt;
      double remCost;&lt;br /&gt;
        int i, j, k;&lt;br /&gt;
        int tr = omp_get_max_threads();&lt;br /&gt;
        bool moved = false;&lt;br /&gt;
    &lt;br /&gt;
    t_num = atoi(argv[1]);&lt;br /&gt;
    t_len = atoi(argv[2]);&lt;br /&gt;
    r = atof(argv[3]);&lt;br /&gt;
    &lt;br /&gt;
      int* Distr = (int*)malloc(t_num * sizeof(int));&lt;br /&gt;
    &lt;br /&gt;
      char** T = (char **)malloc(t_num * sizeof(char*));&lt;br /&gt;
      T[0] = (char *)malloc(t_num * t_len * sizeof(char));&lt;br /&gt;
      for (i=1; i &amp;lt; t_num; i++){&lt;br /&gt;
        T[i] = T[i-1] + t_len;&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
        vector&amp;lt;Clust&amp;gt; C;&lt;br /&gt;
        C.push_back(Clust());&lt;br /&gt;
    &lt;br /&gt;
      FILE* input = fopen(&amp;quot;input.txt&amp;quot;, &amp;quot;r&amp;quot;);&lt;br /&gt;
          for (i = 0; i &amp;lt; t_num; i++) {&lt;br /&gt;
            for (j = 0; j &amp;lt; t_len; j++) {&lt;br /&gt;
              fscanf(input, &amp;quot;%c &amp;quot;, &amp;amp;T[i][j]);&lt;br /&gt;
            }&lt;br /&gt;
          }&lt;br /&gt;
    &lt;br /&gt;
    //Инициализация&lt;br /&gt;
    &lt;br /&gt;
      double tm = omp_get_wtime();&lt;br /&gt;
      AddTransaction(C[0], T[0]);&lt;br /&gt;
      ClusCnt++;&lt;br /&gt;
      C.push_back(Clust());&lt;br /&gt;
    &lt;br /&gt;
        Distr[0] = 0;&lt;br /&gt;
    &lt;br /&gt;
      for (i = 1; i &amp;lt; t_num; i++){&lt;br /&gt;
        maxCost = 0;&lt;br /&gt;
        double add[ClusCnt + 1];&lt;br /&gt;
    &lt;br /&gt;
        #pragma omp parallel for private(j) shared(ClusCnt, add, C, T)&lt;br /&gt;
        for (j = 0; j &amp;lt;= ClusCnt; j++){&lt;br /&gt;
          add[j] = AddCost(C[j], T[i]);&lt;br /&gt;
        }&lt;br /&gt;
    &lt;br /&gt;
          for (j = 0; j &amp;lt;= ClusCnt; j++){&lt;br /&gt;
          if (add[j] &amp;gt; maxCost){&lt;br /&gt;
            maxCost = add[j];&lt;br /&gt;
            bestChoice = j;&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
        if (bestChoice == ClusCnt){&lt;br /&gt;
          ClusCnt++;&lt;br /&gt;
          C.push_back(Clust());&lt;br /&gt;
        }&lt;br /&gt;
        AddTransaction(C[bestChoice], T[i]);&lt;br /&gt;
        Distr[i] = bestChoice;&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
    //Итерации&lt;br /&gt;
      for (k = 0; k &amp;lt; 10; k++){ // k - число итераций&lt;br /&gt;
          moved = false;&lt;br /&gt;
          double add[ClusCnt + 1];&lt;br /&gt;
    &lt;br /&gt;
          for (i = 0; i &amp;lt; t_num; i++){&lt;br /&gt;
           maxCost = 0;&lt;br /&gt;
           remCost = RemoveCost(C[Distr[i]],T[i]);&lt;br /&gt;
    &lt;br /&gt;
           #pragma omp parallel for private(j) shared(ClusCnt, add, C, T, Distr, remCost)&lt;br /&gt;
           for (j = 0; j &amp;lt;= ClusCnt; j++){&lt;br /&gt;
            if (j != Distr[i]) {&lt;br /&gt;
              add[j] = AddCost(C[j], T[i]) + remCost;&lt;br /&gt;
              }&lt;br /&gt;
           }&lt;br /&gt;
            for (j = 0; j &amp;lt;= ClusCnt; j++){&lt;br /&gt;
              if (j != Distr[i]){&lt;br /&gt;
              if (add[j] &amp;gt; maxCost) {&lt;br /&gt;
                maxCost = add[j];&lt;br /&gt;
                bestChoice = j;&lt;br /&gt;
                }&lt;br /&gt;
              }&lt;br /&gt;
            }&lt;br /&gt;
    &lt;br /&gt;
            if (maxCost &amp;gt; 0){&lt;br /&gt;
              if (bestChoice == ClusCnt){&lt;br /&gt;
                ClusCnt++;&lt;br /&gt;
                C.push_back(Clust());&lt;br /&gt;
              }&lt;br /&gt;
              RemoveTransaction(C[Distr[i]], T[i]);&lt;br /&gt;
              AddTransaction(C[bestChoice], T[i]);&lt;br /&gt;
              Distr[i] = bestChoice;&lt;br /&gt;
              moved = true;&lt;br /&gt;
            }&lt;br /&gt;
          }&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
    tm = omp_get_wtime() - tm;&lt;br /&gt;
    &lt;br /&gt;
    printf(&amp;quot;size:%d\twidth:%d\tcl_cnt:%d\threads:%d\ttime:%lf seconds\tr:%lf&amp;quot;,t_num,t_len,ClusCnt - 1,tr,tm,r);&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    FILE* output = fopen(&amp;quot;out.txt&amp;quot;,&amp;quot;w&amp;quot;);&lt;br /&gt;
    for (int j = 0; j &amp;lt;= ClusCnt; j++){&lt;br /&gt;
        fprintf(output,&amp;quot;Cluster %d:\n&amp;quot;,j);&lt;br /&gt;
        for (multiset&amp;lt;char&amp;gt;::iterator it = C[j].clus.begin(); it != C[j].clus.end(); it++){&lt;br /&gt;
                fprintf(output,&amp;quot;%c&amp;quot;,*it);&lt;br /&gt;
        }&lt;br /&gt;
        fprintf(output,&amp;quot;\n&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    fclose(input);&lt;br /&gt;
    fclose(output);&lt;br /&gt;
    free(T[0]);&lt;br /&gt;
    free(T);&lt;br /&gt;
    free(Distr);&lt;br /&gt;
    &lt;br /&gt;
    return 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
* http://weka.sourceforge.net/doc.stable/weka/clusterers/CLOPE.html - реализация в open source библиотеке для анализа данных WEKA(Waikato Environment for Knowledge Analysis) на языке Java&lt;br /&gt;
Также существуют пользовательские реализации алгоритма:&lt;br /&gt;
* https://github.com/infozor/php_mysql_clustering_clope - реализация алгоритма на PHP&lt;br /&gt;
* https://github.com/Tolsi/scala-clope - реализация алгоритма Scala&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:%D0%9F%D0%B0%D0%B2%D0%B5%D0%BB/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BA%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D0%B9%D0%BD%D1%8B%D1%85_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85_CLOPE&amp;diff=22500</id>
		<title>Участник:Павел/Алгоритм кластеризации категорийных данных CLOPE</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9F%D0%B0%D0%B2%D0%B5%D0%BB/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BA%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D0%B9%D0%BD%D1%8B%D1%85_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85_CLOPE&amp;diff=22500"/>
		<updated>2017-02-15T08:00: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;
Алгоритм CLOPE (Clustering with sLOPE&amp;lt;ref&amp;gt;Yang, Y., Guan, H., You. J. CLOPE: A fast and Effective Clustering Algorithm for Transactional Data In Proc. of SIGKDD’02, July 23-26, 2002, Edmonton, Alberta, Canada.&amp;lt;/ref&amp;gt;) неирархический метод кластеризации, предназначенный для кластеризации огромных наборов категорийных данных. К достоинствам алгоритма относятся высокие масштабируемость и скорость работы и качество кластеризации, что достигается использованием глобального критерия оптимизации на основе максимизации градиента высоты гистограммы кластера. Отличается простотой программной реализации. &lt;br /&gt;
&lt;br /&gt;
Во время работы алгоритм хранит в памяти небольшое количество информации по каждому кластеру и требует минимальное число сканирований набора данных. CLOPE автоматически подбирает количество кластеров, причем это регулируется одним единственным параметром - коэффициентом отталкивания &amp;lt;math&amp;gt; r &amp;lt;/math&amp;gt;. При этом он обеспечивает более высокую производительность и лучшее качество кластеризации в сравнении с многими иерархическими алгоритмами.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
Пусть имеется база транзакций &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, состоящая из множества транзакций &amp;lt;math&amp;gt;\{t_1,t_2,...,t_n\}&amp;lt;/math&amp;gt;. Каждая транзакция есть набор объектов &amp;lt;math&amp;gt;\{i_1,...,i_m\}&amp;lt;/math&amp;gt;. Множество кластеров &amp;lt;math&amp;gt;\{C_1,...,C_k\}&amp;lt;/math&amp;gt; есть разбиение множества &amp;lt;math&amp;gt;\{t_1,...,t_n\}&amp;lt;/math&amp;gt;, такое, что &amp;lt;math&amp;gt;C_1 \cup \dots \cup C_k=\{t_1,...,t_n\}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_i \ne \empty&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_i \cap C_j = \empty &amp;lt;/math&amp;gt;, для &amp;lt;math&amp;gt;i \ge 1, k \ge j&amp;lt;/math&amp;gt;. Каждый элемент &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; называется кластером, а &amp;lt;math&amp;gt;n, m, k&amp;lt;/math&amp;gt; – количество транзакций, количество объектов в базе транзакций и число кластеров соответственно.&lt;br /&gt;
&lt;br /&gt;
Каждый кластер &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; имеет следующие характеристики:&lt;br /&gt;
&amp;lt;math&amp;gt;D(C)&amp;lt;/math&amp;gt; – множество уникальных объектов;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;Occ(i,C)&amp;lt;/math&amp;gt; – количество вхождений (частота) объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; в кластер &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;S(C)= \sum_{i \in D(C)} Occ(i,C)= \sum_{t_i \in C}  \mid t_i  \mid , &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;W(C)=  \mid D(C) \mid ,H(C)=S(C)/W(C) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Функция стоимости:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; Profit(C) = \frac{\sum^{k}_{i=1} G(C_i) \times \mid C_i \mid} {\sum^{k}_{i=1} \mid C_i \mid } = \frac{\sum^{k}_{i=1} \frac{S(C_i)}{W(C_i)^r} \times \mid C_i \mid} {\sum^{k}_{i=1} \mid C_i \mid }  &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;\mid C_i \mid&amp;lt;/math&amp;gt;  количество объектов в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом кластере, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; – количество кластеров, &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; – коэффициент отталкивания &amp;lt;math&amp;gt;(0 &amp;lt; r \le 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С помощью параметра &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; регулируется уровень сходства транзакций внутри кластера, и, как&lt;br /&gt;
следствие, финальное количество кластеров. Этот коэффициент подбирается пользователем. Чем больше &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt;, тем ниже уровень сходства и тем больше кластеров будет сгенерировано.&lt;br /&gt;
&lt;br /&gt;
Постановка задачи кластеризации алгоритмом CLOPE выглядит следующим образом: &lt;br /&gt;
&lt;br /&gt;
для заданных &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; найти разбиение &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; такое, что: &lt;br /&gt;
&amp;lt;math&amp;gt;Profit(C) \longrightarrow max &amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит в вычислении на каждой итерации стоимости добавления и удаления транзакции из кластера: &lt;br /&gt;
&lt;br /&gt;
*вычисление нового размера кластера &amp;lt;math&amp;gt;S_{new}(C_i)=S(C_i) \pm \mid(t_n)\mid &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\mid(t_n)\mid&amp;lt;/math&amp;gt; - длина транзакции&lt;br /&gt;
&lt;br /&gt;
*вычисление новой ширины кластера &amp;lt;math&amp;gt;W_{new}(C_i)=\mid D(C_i \cup t_n)|&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*вычисление стоимости &amp;lt;math&amp;gt;\frac{S_{new}(C_i)(\mid C_i \mid \pm 1)}{W_{new}(C_i)^r} - \frac{S(C_i) \mid C_i \mid }{W(C_i)^r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм состоит из следующих этапов:&lt;br /&gt;
&lt;br /&gt;
1. &#039;&#039;&#039;Инициализация&#039;&#039;&#039;. На этом этапе происходит первый проход по таблице с транзакциями для построения начального разбиения, для каждой транзакции определяется кластер исходя из максимизации стоимости.&lt;br /&gt;
&lt;br /&gt;
2. &#039;&#039;&#039;Итерация&#039;&#039;&#039;. На данном этапе для каждой транзакции проводится попытка перемещения в другой кластер для максимизации функции стоимости.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
[[File:InitIter.PNG||500px]]&lt;br /&gt;
&lt;br /&gt;
Первая часть алгоритма - инициализация: для каждой транзакции вычисляется кластер, к которому она будет отнесена исходя из максимизации функции стоимости. Для этого вычисляется вспомогательная функция DeltaAdd, которая считает стоимость добавления транзакции к одному из существующих кластеров, либо к пустому. В итоге транзакция помещается в кластер, для которого цена добавления максимальна.&lt;br /&gt;
&lt;br /&gt;
Вторая часть алгоритма - уточняющие итерации: здесь происходит попытка улучшить вычисленные на первом этапе кластеры. В каждой итерации происходит перебор всех транзакций, и для каждой транзакции вычисляется цена удаления ее из текущего кластера и цена добавления в другой кластер. Суммарная стоимость перемещения будет являться суммой стоимостей удаления и добавления. Если максимальная стоимость перемещения данной транзакции в какой-либо больше нуля, то она перемещается в этот кластер. &lt;br /&gt;
&lt;br /&gt;
Вычисления происходят до тех пор, пока за итерацию происходит хотя бы одно перемещение транзакции. Если за итерацию не было произведено ни одного перемещения, то текущее состояние кластеров является устойчивым и оптимальным. &amp;lt;ref&amp;gt;Павлин Н. Кластеризация категорийных данных: масштабируемый алгоритм CLOPE, https://basegroup.ru/community/articles/clope&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Схема реализации на псевдокоде:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Входные параметры:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - транзакции&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; - коэффициент отталкивания&lt;br /&gt;
&lt;br /&gt;
Выходной параметр:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; кластеры, в начале алгоритма - пустое множество&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация:&#039;&#039;&#039;&lt;br /&gt;
    &#039;&#039;&#039;for&#039;&#039;&#039; t_i in t:&lt;br /&gt;
    max = 0&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; C_j in C:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; DeltaAdd(C_j,t_i,r) &amp;gt; max:&lt;br /&gt;
                max = DeltaAdd(C_j,t_i,r)&lt;br /&gt;
                C_best = C_j&lt;br /&gt;
    &#039;&#039;&#039;put&#039;&#039;&#039; t_i in C_best&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Итерации:&#039;&#039;&#039;&lt;br /&gt;
    move = True&lt;br /&gt;
    &#039;&#039;&#039;while&#039;&#039;&#039; move == True:&lt;br /&gt;
    move = False&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; t_i in t:&lt;br /&gt;
            max = 0&lt;br /&gt;
            C_now = t_i.cluster&lt;br /&gt;
            removeCost = DeltaRemove(C_now,t_i,r)&lt;br /&gt;
            &#039;&#039;&#039;for&#039;&#039;&#039; C_j in C:&lt;br /&gt;
                &#039;&#039;&#039;if&#039;&#039;&#039; DeltaAdd(C_j,t_i,r) + removeCost &amp;gt; max:&lt;br /&gt;
                    max = DeltaAdd(C_j,t_i,r) + removeCost&lt;br /&gt;
                    C_best = C_j&lt;br /&gt;
        if max &amp;gt; 0&lt;br /&gt;
            &#039;&#039;&#039;del&#039;&#039;&#039; t_i from C_now&lt;br /&gt;
            &#039;&#039;&#039;put&#039;&#039;&#039; t_i in C_best&lt;br /&gt;
            move = True&lt;br /&gt;
&lt;br /&gt;
Вспомогательная функция &#039;&#039;&#039;DeltaAdd&#039;&#039;&#039;:&lt;br /&gt;
    &#039;&#039;&#039;function&#039;&#039;&#039; DeltaAdd(C,t,r)&lt;br /&gt;
        S_new=C.size + t.itemCount&lt;br /&gt;
        W_new=C.wigth&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; item in t_i:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; C_j.occ(item) = 0&lt;br /&gt;
                &#039;&#039;W_new = W_new + 1&lt;br /&gt;
        &#039;&#039;&#039;return&#039;&#039;&#039; S_new * (C.count+1) / (W_new ^ r) - (C.size * C.count) / (C.wigth ^ r)&lt;br /&gt;
&lt;br /&gt;
Вспомогательная функция &#039;&#039;&#039;DeltaRemove&#039;&#039;&#039;:&lt;br /&gt;
    &#039;&#039;&#039;function&#039;&#039;&#039; DeltaRemove(C,t,r)&lt;br /&gt;
        S_new=C.size - t.itemCount&lt;br /&gt;
        W_new=C.wigth&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; item in t:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; C_j.occ(item) = 1&lt;br /&gt;
                &#039;&#039;W_new = W_new - 1&lt;br /&gt;
        &#039;&#039;&#039;return&#039;&#039;&#039; S_new * (C.count-1) / (W_new ^ r) - (C.size * C.count) / (C.wigth ^ r)&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
В соответствии с ранее введенным обозначением &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - количество транзакций, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина транзакции(максимальная), &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество кластеров.&lt;br /&gt;
&lt;br /&gt;
Основные вычисления восполняются в функции DeltaAdd/DeltaRemove: производится 1 сложение, не более &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; сложений/вычитаний, 2 умножения, 2 деления, 2 возведения в степень и 1 сложение - итого &amp;lt;math&amp;gt;m + 8&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;k&amp;lt;/math&amp;gt; штук). Итого выполняется &amp;lt;math&amp;gt;n*k*(m+8)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
В добавок к этому при добавлении/удалении транзакции к кластеру производится пересчет его характеристик: &amp;lt;math&amp;gt;m+2&amp;lt;/math&amp;gt; операции.&lt;br /&gt;
&lt;br /&gt;
Из того можно сделать вывод, что оценка сложность алгоритма равна &amp;lt;math&amp;gt;O(n*k*m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
&lt;br /&gt;
На рисунке ниже представлена схема этапа инициализации на примере входной транзакции &#039;&#039;&#039;T&#039;&#039;&#039; и четырех кластеров &#039;&#039;&#039;Cl 1&#039;&#039;&#039;, &#039;&#039;&#039;Cl 2&#039;&#039;&#039;, &#039;&#039;&#039;Cl 3&#039;&#039;&#039; и &#039;&#039;&#039;Cl 4&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Объект &#039;&#039;&#039;DeltaAdd&#039;&#039;&#039; соответствует выполнению соответствующей функции для вычисления цены добавления транзакции на кластер. После выполнения всех &#039;&#039;&#039;DeltaAdd&#039;&#039;&#039; для одной транзакции выполняется определение максимального значения функции и выбор кластера, на который будет помещена транзакция. На этапе инициализации при обработке каждой транзакции количество кластеров может как увеличиться, так и остаться неизменным.&lt;br /&gt;
&lt;br /&gt;
[[File:InitDef.PNG||700px]]&lt;br /&gt;
&lt;br /&gt;
Этап итераций отличается только тем, что на нем дополнительно считается функция &#039;&#039;&#039;DeltaRemove&#039;&#039;&#039; вычисления стоимости удаления транзакции с кластера. На этапе итерации функции DeltaAdd/DeltaRemove могут считать параллельно для каждой транзакции.&lt;br /&gt;
&lt;br /&gt;
Синие точки сетки - вычисление функций DeltaAdd. На этапе инициализации количество кластеров может как увеличиться, так и не измениться, это показано пунктирными линиями.&lt;br /&gt;
[[File:init1.PNG|thumb|center|300px|Этап Инициализации]]&lt;br /&gt;
&lt;br /&gt;
Зеленые точки сетки - вычисление функций DeltaAdd и DeltaRemove. На этапе итераций функции могут считаться параллельно для каждой транзакции.&lt;br /&gt;
[[File:iter1.PNG|thumb|center|300px|Этап Итераций]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Вычисление стоимости добавления/удаления транзакции, которые выполняются функциями DeltaAdd/DeltaRemove, происходит независимо для всех &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; кластеров. Поэтому все вычисления можно производить параллельно. Таким образом сложность алгоритма с &amp;lt;math&amp;gt;O(n*k*m)&amp;lt;/math&amp;gt; понижается до &amp;lt;math&amp;gt;O(n*m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; транзакций длины &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; и коэффициент отталкивания &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
метки классов для каждой транзакции в соответствии с проведенной кластеризацией(числовая последовательность длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной сложности алгоритма определяется количеством кластеров: &amp;lt;math&amp;gt;\dfrac{O(n*k*m)}{O(n*m)} = k&amp;lt;/math&amp;gt;&lt;br /&gt;
* [[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]] алгоритма равна &amp;lt;math&amp;gt;\dfrac{nk(m+8) + m + 2}{nm + n + 1} \cong k&amp;lt;/math&amp;gt;&lt;br /&gt;
* Алгоритм не является [[глоссарий#Устойчивость|&#039;&#039;устойчивым&#039;&#039;]], так как результат работы зависит от порядка чтения транзакций и от текущего набора транзакций в кластере.&lt;br /&gt;
* Выполняется свойство сбалансированности операций между параллельными ветвями алгоритма, так как для каждой транзакции выполняются функции DeltaAdd/DeltaRemove, считающие стоимость добавления/удаления транзакции.&lt;br /&gt;
* Свойство [[глоссарий#Детерминированность|&#039;&#039;детерминированности алгоритмов&#039;&#039;]] не выполняется, так как результат алгоритма зависит от порядка прохождения транзакций. Но если рассматривать транзакции как нумерованный список, то результат будет определен однозначно от запуска к запуску. Однако существует расширение алгоритма, обеспечивающее свойство детерминированности. &amp;lt;ref&amp;gt;Li, Y., Le, J., Wang, M. Improving CLOPE’s Profit Value and Stability with an Optimized Agglomerative Approach. Algorithms 2015, 8, 380-394.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
* Так как алгоритм предназначен для кластеризации категориальных данных, то он практически неприменим для числовой кластеризации.&lt;br /&gt;
* Быстро работает даже для большого количества данных, обеспечивая при этом хорошее качество кластеризации&lt;br /&gt;
* Имеет простую реализацию&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
Проверка масштабируемости проводилась на суперкомпьютере &amp;quot;Ломоносов&amp;quot; с использованием компилятора Intel(13.1.0) и стандарта OpenMP для 1000, 2000, 3000, 4000 и 5000 транзакций из пяти латинских букв с использованием 1, 2, 4, 8 и 16 нитей. Использованные параметры компиляции и запуска:&lt;br /&gt;
&lt;br /&gt;
    icc -openmp CLOPE.cpp -o clope&lt;br /&gt;
    &lt;br /&gt;
    export OMP_NUM_THREADS = k (k - число нитей)&lt;br /&gt;
    sbatch -p test -N 1 run ./clope tr 5 3 (tr - количество транзакций)&lt;br /&gt;
&lt;br /&gt;
Используемая реализация:&lt;br /&gt;
&lt;br /&gt;
    #include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
    #include &amp;lt;cstdlib&amp;gt;&lt;br /&gt;
    #include &amp;lt;cmath&amp;gt;&lt;br /&gt;
    #include &amp;lt;cstring&amp;gt;&lt;br /&gt;
    #include &amp;lt;set&amp;gt;&lt;br /&gt;
    #include &amp;lt;vector&amp;gt;&lt;br /&gt;
    #include &amp;quot;omp.h&amp;quot;&lt;br /&gt;
    &lt;br /&gt;
    using namespace std;&lt;br /&gt;
    &lt;br /&gt;
    double r = 1.6;&lt;br /&gt;
    int t_num = 5000;&lt;br /&gt;
    int t_len = 5;&lt;br /&gt;
    &lt;br /&gt;
    struct Clust&lt;br /&gt;
    {&lt;br /&gt;
      int size;&lt;br /&gt;
      int count;&lt;br /&gt;
      int width;&lt;br /&gt;
      multiset &amp;lt;char&amp;gt; clus;&lt;br /&gt;
      Clust(){&lt;br /&gt;
          size = 0;&lt;br /&gt;
          count = 0;&lt;br /&gt;
          width = 0;}&lt;br /&gt;
    };&lt;br /&gt;
    &lt;br /&gt;
    void AddTransaction(Clust &amp;amp;C, char* t)&lt;br /&gt;
    {&lt;br /&gt;
      C.size = C.size + t_len;&lt;br /&gt;
      C.count = C.count + 1;&lt;br /&gt;
    &lt;br /&gt;
      for (int i = 0; i &amp;lt; t_len; i++){&lt;br /&gt;
        if (C.clus.count(t[i]) == 0) {&lt;br /&gt;
          C.width = C.width + 1;&lt;br /&gt;
        }&lt;br /&gt;
        C.clus.insert(t[i]);&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    void RemoveTransaction(Clust &amp;amp;C, char* t)&lt;br /&gt;
    {&lt;br /&gt;
      C.size = C.size - t_len;&lt;br /&gt;
      C.count = C.count - 1;&lt;br /&gt;
    &lt;br /&gt;
      for (int i = 0; i &amp;lt; t_len; i++){&lt;br /&gt;
        if (C.clus.count(t[i]) == 1) {&lt;br /&gt;
          C.width = C.width - 1;&lt;br /&gt;
        }&lt;br /&gt;
        C.clus.erase(C.clus.find(t[i]));&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    double AddCost(Clust C, char* t)&lt;br /&gt;
    {&lt;br /&gt;
      int S = C.size;&lt;br /&gt;
      int N = C.count;&lt;br /&gt;
      int W = C.width;&lt;br /&gt;
      int Snew = S + t_len;&lt;br /&gt;
      int Nnew = N + 1;&lt;br /&gt;
      int Wnew = W;&lt;br /&gt;
      set &amp;lt;int&amp;gt; tmp;&lt;br /&gt;
    &lt;br /&gt;
      for (int i = 0; i &amp;lt; t_len; i++){&lt;br /&gt;
        if (C.clus.count(t[i]) == 0 &amp;amp;&amp;amp; tmp.count(t[i]) == 0) {&lt;br /&gt;
          Wnew = Wnew + 1;&lt;br /&gt;
        }&lt;br /&gt;
        tmp.insert(t[i]);&lt;br /&gt;
      }&lt;br /&gt;
      return (Snew * Nnew) / (pow(Wnew, r)) - ((S == 0) ? 0 : (S * N) / (pow(W, r)));&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    double RemoveCost(Clust C, char* t)&lt;br /&gt;
    {&lt;br /&gt;
      int S = C.size;&lt;br /&gt;
      int N = C.count;&lt;br /&gt;
      int W = C.width;&lt;br /&gt;
      int Snew = S - t_len;&lt;br /&gt;
      int Nnew = N - 1;&lt;br /&gt;
      int Wnew = W;&lt;br /&gt;
    &lt;br /&gt;
      for (int i = 0; i &amp;lt; t_len; i++){&lt;br /&gt;
        if (C.clus.count(t[i]) == 1) {&lt;br /&gt;
          Wnew = Wnew - 1;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      return ((Wnew == 0) ? 0 : (Snew * Nnew) / (pow(Wnew, r))) - (S * N) / (pow(W, r));&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    int main(int argc, char **argv)&lt;br /&gt;
    {&lt;br /&gt;
      int ClusCnt = 0;&lt;br /&gt;
      double maxCost;&lt;br /&gt;
      int bestChoice;&lt;br /&gt;
      double remCost;&lt;br /&gt;
        int i, j, k;&lt;br /&gt;
        int tr = omp_get_max_threads();&lt;br /&gt;
        bool moved = false;&lt;br /&gt;
    &lt;br /&gt;
    t_num = atoi(argv[1]);&lt;br /&gt;
    t_len = atoi(argv[2]);&lt;br /&gt;
    r = atof(argv[3]);&lt;br /&gt;
    &lt;br /&gt;
      int* Distr = (int*)malloc(t_num * sizeof(int));&lt;br /&gt;
    &lt;br /&gt;
      char** T = (char **)malloc(t_num * sizeof(char*));&lt;br /&gt;
      T[0] = (char *)malloc(t_num * t_len * sizeof(char));&lt;br /&gt;
      for (i=1; i &amp;lt; t_num; i++){&lt;br /&gt;
        T[i] = T[i-1] + t_len;&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
        vector&amp;lt;Clust&amp;gt; C;&lt;br /&gt;
        C.push_back(Clust());&lt;br /&gt;
    &lt;br /&gt;
      FILE* input = fopen(&amp;quot;input.txt&amp;quot;, &amp;quot;r&amp;quot;);&lt;br /&gt;
          for (i = 0; i &amp;lt; t_num; i++) {&lt;br /&gt;
            for (j = 0; j &amp;lt; t_len; j++) {&lt;br /&gt;
              fscanf(input, &amp;quot;%c &amp;quot;, &amp;amp;T[i][j]);&lt;br /&gt;
            }&lt;br /&gt;
          }&lt;br /&gt;
    &lt;br /&gt;
    //Инициализация&lt;br /&gt;
    &lt;br /&gt;
      double tm = omp_get_wtime();&lt;br /&gt;
      AddTransaction(C[0], T[0]);&lt;br /&gt;
      ClusCnt++;&lt;br /&gt;
      C.push_back(Clust());&lt;br /&gt;
    &lt;br /&gt;
        Distr[0] = 0;&lt;br /&gt;
    &lt;br /&gt;
      for (i = 1; i &amp;lt; t_num; i++){&lt;br /&gt;
        maxCost = 0;&lt;br /&gt;
        double add[ClusCnt + 1];&lt;br /&gt;
    &lt;br /&gt;
        #pragma omp parallel for private(j) shared(ClusCnt, add, C, T)&lt;br /&gt;
        for (j = 0; j &amp;lt;= ClusCnt; j++){&lt;br /&gt;
          add[j] = AddCost(C[j], T[i]);&lt;br /&gt;
        }&lt;br /&gt;
    &lt;br /&gt;
          for (j = 0; j &amp;lt;= ClusCnt; j++){&lt;br /&gt;
          if (add[j] &amp;gt; maxCost){&lt;br /&gt;
            maxCost = add[j];&lt;br /&gt;
            bestChoice = j;&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
        if (bestChoice == ClusCnt){&lt;br /&gt;
          ClusCnt++;&lt;br /&gt;
          C.push_back(Clust());&lt;br /&gt;
        }&lt;br /&gt;
        AddTransaction(C[bestChoice], T[i]);&lt;br /&gt;
        Distr[i] = bestChoice;&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
    //Итерации&lt;br /&gt;
      for (k = 0; k &amp;lt; 10; k++){ // k - число итераций&lt;br /&gt;
          moved = false;&lt;br /&gt;
          double add[ClusCnt + 1];&lt;br /&gt;
    &lt;br /&gt;
          for (i = 0; i &amp;lt; t_num; i++){&lt;br /&gt;
           maxCost = 0;&lt;br /&gt;
           remCost = RemoveCost(C[Distr[i]],T[i]);&lt;br /&gt;
    &lt;br /&gt;
           #pragma omp parallel for private(j) shared(ClusCnt, add, C, T, Distr, remCost)&lt;br /&gt;
           for (j = 0; j &amp;lt;= ClusCnt; j++){&lt;br /&gt;
            if (j != Distr[i]) {&lt;br /&gt;
              add[j] = AddCost(C[j], T[i]) + remCost;&lt;br /&gt;
              }&lt;br /&gt;
           }&lt;br /&gt;
            for (j = 0; j &amp;lt;= ClusCnt; j++){&lt;br /&gt;
              if (j != Distr[i]){&lt;br /&gt;
              if (add[j] &amp;gt; maxCost) {&lt;br /&gt;
                maxCost = add[j];&lt;br /&gt;
                bestChoice = j;&lt;br /&gt;
                }&lt;br /&gt;
              }&lt;br /&gt;
            }&lt;br /&gt;
    &lt;br /&gt;
            if (maxCost &amp;gt; 0){&lt;br /&gt;
              if (bestChoice == ClusCnt){&lt;br /&gt;
                ClusCnt++;&lt;br /&gt;
                C.push_back(Clust());&lt;br /&gt;
              }&lt;br /&gt;
              RemoveTransaction(C[Distr[i]], T[i]);&lt;br /&gt;
              AddTransaction(C[bestChoice], T[i]);&lt;br /&gt;
              Distr[i] = bestChoice;&lt;br /&gt;
              moved = true;&lt;br /&gt;
            }&lt;br /&gt;
          }&lt;br /&gt;
      }&lt;br /&gt;
    &lt;br /&gt;
    tm = omp_get_wtime() - tm;&lt;br /&gt;
    &lt;br /&gt;
    printf(&amp;quot;size:%d\twidth:%d\tcl_cnt:%d\threads:%d\ttime:%lf seconds\tr:%lf&amp;quot;,t_num,t_len,ClusCnt - 1,tr,tm,r);&lt;br /&gt;
    &lt;br /&gt;
    &lt;br /&gt;
    FILE* output = fopen(&amp;quot;out.txt&amp;quot;,&amp;quot;w&amp;quot;);&lt;br /&gt;
    for (int j = 0; j &amp;lt;= ClusCnt; j++){&lt;br /&gt;
        fprintf(output,&amp;quot;Cluster %d:\n&amp;quot;,j);&lt;br /&gt;
        for (multiset&amp;lt;char&amp;gt;::iterator it = C[j].clus.begin(); it != C[j].clus.end(); it++){&lt;br /&gt;
                fprintf(output,&amp;quot;%c&amp;quot;,*it);&lt;br /&gt;
        }&lt;br /&gt;
        fprintf(output,&amp;quot;\n&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    fclose(input);&lt;br /&gt;
    fclose(output);&lt;br /&gt;
    free(T[0]);&lt;br /&gt;
    free(T);&lt;br /&gt;
    free(Distr);&lt;br /&gt;
    &lt;br /&gt;
    return 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Результаты проверки на графике ниже.&lt;br /&gt;
&lt;br /&gt;
//[[file:Graf_lom.png||700px]]&lt;br /&gt;
&lt;br /&gt;
//Таким образом, можно сделать вывод о том, что алгоритм кластеризации CLOPE является масштабируемым.&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
* http://weka.sourceforge.net/doc.stable/weka/clusterers/CLOPE.html - реализация в open source библиотеке для анализа данных WEKA(Waikato Environment for Knowledge Analysis) на языке Java&lt;br /&gt;
Также существуют пользовательские реализации алгоритма:&lt;br /&gt;
* https://github.com/infozor/php_mysql_clustering_clope - реализация алгоритма на PHP&lt;br /&gt;
* https://github.com/Tolsi/scala-clope - реализация алгоритма Scala&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:%D0%9F%D0%B0%D0%B2%D0%B5%D0%BB/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BA%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D0%B9%D0%BD%D1%8B%D1%85_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85_CLOPE&amp;diff=22342</id>
		<title>Участник:Павел/Алгоритм кластеризации категорийных данных CLOPE</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9F%D0%B0%D0%B2%D0%B5%D0%BB/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BA%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D0%B9%D0%BD%D1%8B%D1%85_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85_CLOPE&amp;diff=22342"/>
		<updated>2017-02-06T21:00:48Z</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;
Алгоритм CLOPE (Clustering with sLOPE&amp;lt;ref&amp;gt;Yang, Y., Guan, H., You. J. CLOPE: A fast and Effective Clustering Algorithm for Transactional Data In Proc. of SIGKDD’02, July 23-26, 2002, Edmonton, Alberta, Canada.&amp;lt;/ref&amp;gt;) неирархический метод кластеризации, предназначенный для кластеризации огромных наборов категорийных данных. К достоинствам алгоритма относятся высокие масштабируемость и скорость работы и качество кластеризации, что достигается использованием глобального критерия оптимизации на основе максимизации градиента высоты гистограммы кластера. Отличается простотой программной реализации. &lt;br /&gt;
&lt;br /&gt;
Во время работы алгоритм хранит в памяти небольшое количество информации по каждому кластеру и требует минимальное число сканирований набора данных. CLOPE автоматически подбирает количество кластеров, причем это регулируется одним единственным параметром - коэффициентом отталкивания &amp;lt;math&amp;gt; r &amp;lt;/math&amp;gt;. При этом он обеспечивает более высокую производительность и лучшее качество кластеризации в сравнении с многими иерархическими алгоритмами.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
Пусть имеется база транзакций &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, состоящая из множества транзакций &amp;lt;math&amp;gt;\{t_1,t_2,...,t_n\}&amp;lt;/math&amp;gt;. Каждая транзакция есть набор объектов &amp;lt;math&amp;gt;\{i_1,...,i_m\}&amp;lt;/math&amp;gt;. Множество кластеров &amp;lt;math&amp;gt;\{C_1,...,C_k\}&amp;lt;/math&amp;gt; есть разбиение множества &amp;lt;math&amp;gt;\{t_1,...,t_n\}&amp;lt;/math&amp;gt;, такое, что &amp;lt;math&amp;gt;C_1 \cup \dots \cup C_k=\{t_1,...,t_n\}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_i \ne \empty&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_i \cap C_j = \empty &amp;lt;/math&amp;gt;, для &amp;lt;math&amp;gt;i \ge 1, k \ge j&amp;lt;/math&amp;gt;. Каждый элемент &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; называется кластером, а &amp;lt;math&amp;gt;n, m, k&amp;lt;/math&amp;gt; – количество транзакций, количество объектов в базе транзакций и число кластеров соответственно.&lt;br /&gt;
&lt;br /&gt;
Каждый кластер &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; имеет следующие характеристики:&lt;br /&gt;
&amp;lt;math&amp;gt;D(C)&amp;lt;/math&amp;gt; – множество уникальных объектов;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;Occ(i,C)&amp;lt;/math&amp;gt; – количество вхождений (частота) объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; в кластер &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;S(C)= \sum_{i \in D(C)} Occ(i,C)= \sum_{t_i \in C}  \mid t_i  \mid , &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;W(C)=  \mid D(C) \mid ,H(C)=S(C)/W(C) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Функция стоимости:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; Profit(C) = \frac{\sum^{k}_{i=1} G(C_i) \times \mid C_i \mid} {\sum^{k}_{i=1} \mid C_i \mid } = \frac{\sum^{k}_{i=1} \frac{S(C_i)}{W(C_i)^r} \times \mid C_i \mid} {\sum^{k}_{i=1} \mid C_i \mid }  &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;\mid C_i \mid&amp;lt;/math&amp;gt;  количество объектов в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом кластере, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; – количество кластеров, &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; – коэффициент отталкивания &amp;lt;math&amp;gt;(0 &amp;lt; r \le 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С помощью параметра &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; регулируется уровень сходства транзакций внутри кластера, и, как&lt;br /&gt;
следствие, финальное количество кластеров. Этот коэффициент подбирается пользователем. Чем больше &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt;, тем ниже уровень сходства и тем больше кластеров будет сгенерировано.&lt;br /&gt;
&lt;br /&gt;
Постановка задачи кластеризации алгоритмом CLOPE выглядит следующим образом: &lt;br /&gt;
&lt;br /&gt;
для заданных &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; найти разбиение &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; такое, что: &lt;br /&gt;
&amp;lt;math&amp;gt;Profit(C) \longrightarrow max &amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит в вычислении на каждой итерации стоимости добавления и удаления транзакции из кластера: &lt;br /&gt;
&lt;br /&gt;
*вычисление нового размера кластера &amp;lt;math&amp;gt;S_{new}(C_i)=S(C_i) \pm \mid(t_n)\mid &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\mid(t_n)\mid&amp;lt;/math&amp;gt; - длина транзакции&lt;br /&gt;
&lt;br /&gt;
*вычисление новой ширины кластера &amp;lt;math&amp;gt;W_{new}(C_i)=\mid D(C_i \cup t_n)|&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*вычисление стоимости &amp;lt;math&amp;gt;\frac{S_{new}(C_i)(\mid C_i \mid \pm 1)}{W_{new}(C_i)^r} - \frac{S(C_i) \mid C_i \mid }{W(C_i)^r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм состоит из следующих этапов:&lt;br /&gt;
&lt;br /&gt;
1. &#039;&#039;&#039;Инициализация&#039;&#039;&#039;. На этом этапе происходит первый проход по таблице с транзакциями для построения начального разбиения, для каждой транзакции определяется кластер исходя из максимизации стоимости.&lt;br /&gt;
&lt;br /&gt;
2. &#039;&#039;&#039;Итерация&#039;&#039;&#039;. На данном этапе для каждой транзакции проводится попытка перемещения в другой кластер для максимизации функции стоимости.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
[[File:InitIter.PNG||500px]]&lt;br /&gt;
&lt;br /&gt;
Первая часть алгоритма - инициализация: для каждой транзакции вычисляется кластер, к которому она будет отнесена исходя из максимизации функции стоимости. Для этого вычисляется вспомогательная функция DeltaAdd, которая считает стоимость добавления транзакции к одному из существующих кластеров, либо к пустому. В итоге транзакция помещается в кластер, для которого цена добавления максимальна.&lt;br /&gt;
&lt;br /&gt;
Вторая часть алгоритма - уточняющие итерации: здесь происходит попытка улучшить вычисленные на первом этапе кластеры. В каждой итерации происходит перебор всех транзакций, и для каждой транзакции вычисляется цена удаления ее из текущего кластера и цена добавления в другой кластер. Суммарная стоимость перемещения будет являться суммой стоимостей удаления и добавления. Если максимальная стоимость перемещения данной транзакции в какой-либо больше нуля, то она перемещается в этот кластер. &lt;br /&gt;
&lt;br /&gt;
Вычисления происходят до тех пор, пока за итерацию происходит хотя бы одно перемещение транзакции. Если за итерацию не было произведено ни одного перемещения, то текущее состояние кластеров является устойчивым и оптимальным. &amp;lt;ref&amp;gt;Павлин Н. Кластеризация категорийных данных: масштабируемый алгоритм CLOPE, https://basegroup.ru/community/articles/clope&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Схема реализации на псевдокоде:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Входные параметры:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - транзакции&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; - коэффициент отталкивания&lt;br /&gt;
&lt;br /&gt;
Выходной параметр:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; кластеры, в начале алгоритма - пустое множество&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация:&#039;&#039;&#039;&lt;br /&gt;
    &#039;&#039;&#039;for&#039;&#039;&#039; t_i in t:&lt;br /&gt;
    max = 0&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; C_j in C:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; DeltaAdd(C_j,t_i,r) &amp;gt; max:&lt;br /&gt;
                max = DeltaAdd(C_j,t_i,r)&lt;br /&gt;
                C_best = C_j&lt;br /&gt;
    &#039;&#039;&#039;put&#039;&#039;&#039; t_i in C_best&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Итерации:&#039;&#039;&#039;&lt;br /&gt;
    move = True&lt;br /&gt;
    &#039;&#039;&#039;while&#039;&#039;&#039; move == True:&lt;br /&gt;
    move = False&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; t_i in t:&lt;br /&gt;
            max = 0&lt;br /&gt;
            C_now = t_i.cluster&lt;br /&gt;
            removeCost = DeltaRemove(C_now,t_i,r)&lt;br /&gt;
            &#039;&#039;&#039;for&#039;&#039;&#039; C_j in C:&lt;br /&gt;
                &#039;&#039;&#039;if&#039;&#039;&#039; DeltaAdd(C_j,t_i,r) + removeCost &amp;gt; max:&lt;br /&gt;
                    max = DeltaAdd(C_j,t_i,r) + removeCost&lt;br /&gt;
                    C_best = C_j&lt;br /&gt;
        if max &amp;gt; 0&lt;br /&gt;
            &#039;&#039;&#039;del&#039;&#039;&#039; t_i from C_now&lt;br /&gt;
            &#039;&#039;&#039;put&#039;&#039;&#039; t_i in C_best&lt;br /&gt;
            move = True&lt;br /&gt;
&lt;br /&gt;
Вспомогательная функция &#039;&#039;&#039;DeltaAdd&#039;&#039;&#039;:&lt;br /&gt;
    &#039;&#039;&#039;function&#039;&#039;&#039; DeltaAdd(C,t,r)&lt;br /&gt;
        S_new=C.size + t.itemCount&lt;br /&gt;
        W_new=C.wigth&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; item in t_i:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; C_j.occ(item) = 0&lt;br /&gt;
                &#039;&#039;W_new = W_new + 1&lt;br /&gt;
        &#039;&#039;&#039;return&#039;&#039;&#039; S_new * (C.count+1) / (W_new ^ r) - (C.size * C.count) / (C.wigth ^ r)&lt;br /&gt;
&lt;br /&gt;
Вспомогательная функция &#039;&#039;&#039;DeltaRemove&#039;&#039;&#039;:&lt;br /&gt;
    &#039;&#039;&#039;function&#039;&#039;&#039; DeltaRemove(C,t,r)&lt;br /&gt;
        S_new=C.size - t.itemCount&lt;br /&gt;
        W_new=C.wigth&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; item in t:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; C_j.occ(item) = 1&lt;br /&gt;
                &#039;&#039;W_new = W_new - 1&lt;br /&gt;
        &#039;&#039;&#039;return&#039;&#039;&#039; S_new * (C.count-1) / (W_new ^ r) - (C.size * C.count) / (C.wigth ^ r)&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
В соответствии с ранее введенным обозначением &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - количество транзакций, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина транзакции(максимальная), &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество кластеров.&lt;br /&gt;
&lt;br /&gt;
Основные вычисления восполняются в функции DeltaAdd/DeltaRemove: производится 1 сложение, не более &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; сложений/вычитаний, 2 умножения, 2 деления, 2 возведения в степень и 1 сложение - итого &amp;lt;math&amp;gt;m + 8&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;k&amp;lt;/math&amp;gt; штук). Итого выполняется &amp;lt;math&amp;gt;n*k*(m+8)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
В добавок к этому при добавлении/удалении транзакции к кластеру производится пересчет его характеристик: &amp;lt;math&amp;gt;m+2&amp;lt;/math&amp;gt; операции.&lt;br /&gt;
&lt;br /&gt;
Из того можно сделать вывод, что оценка сложность алгоритма равна &amp;lt;math&amp;gt;O(n*k*m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
&lt;br /&gt;
На рисунке ниже представлена схема этапа инициализации на примере входной транзакции &#039;&#039;&#039;T&#039;&#039;&#039; и четырех кластеров &#039;&#039;&#039;Cl 1&#039;&#039;&#039;, &#039;&#039;&#039;Cl 2&#039;&#039;&#039;, &#039;&#039;&#039;Cl 3&#039;&#039;&#039; и &#039;&#039;&#039;Cl 4&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Объект &#039;&#039;&#039;DeltaAdd&#039;&#039;&#039; соответствует выполнению соответствующей функции для вычисления цены добавления транзакции на кластер. После выполнения всех &#039;&#039;&#039;DeltaAdd&#039;&#039;&#039; для одной транзакции выполняется определение максимального значения функции и выбор кластера, на который будет помещена транзакция. На этапе инициализации при обработке каждой транзакции количество кластеров может как увеличиться, так и остаться неизменным.&lt;br /&gt;
&lt;br /&gt;
[[File:InitDef.PNG||700px]]&lt;br /&gt;
&lt;br /&gt;
Этап итераций отличается только тем, что на нем дополнительно считается функция &#039;&#039;&#039;DeltaRemove&#039;&#039;&#039; вычисления стоимости удаления транзакции с кластера. На этапе итерации функции DeltaAdd/DeltaRemove могут считать параллельно для каждой транзакции.&lt;br /&gt;
&lt;br /&gt;
Синие точки сетки - вычисление функций DeltaAdd. На этапе инициализации количество кластеров может как увеличиться, так и не измениться, это показано пунктирными линиями.&lt;br /&gt;
[[File:init1.PNG|thumb|center|300px|Этап Инициализации]]&lt;br /&gt;
&lt;br /&gt;
Зеленые точки сетки - вычисление функций DeltaAdd и DeltaRemove. На этапе итераций функции могут считаться параллельно для каждой транзакции.&lt;br /&gt;
[[File:iter1.PNG|thumb|center|300px|Этап Итераций]]&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Вычисление стоимости добавления/удаления транзакции, которые выполняются функциями DeltaAdd/DeltaRemove, происходит независимо для всех &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; кластеров. Поэтому все вычисления можно производить параллельно. Таким образом сложность алгоритма с &amp;lt;math&amp;gt;O(n*k*m)&amp;lt;/math&amp;gt; понижается до &amp;lt;math&amp;gt;O(n*m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; транзакций длины &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; и коэффициент отталкивания &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
метки классов для каждой транзакции в соответствии с проведенной кластеризацией(числовая последовательность длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной сложности алгоритма определяется количеством кластеров: &amp;lt;math&amp;gt;\dfrac{O(n*k*m)}{O(n*m)} = k&amp;lt;/math&amp;gt;&lt;br /&gt;
* [[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]] алгоритма равна &amp;lt;math&amp;gt;\dfrac{nk(m+8) + m + 2}{nm + n + 1} \cong k&amp;lt;/math&amp;gt;&lt;br /&gt;
* Алгоритм не является [[глоссарий#Устойчивость|&#039;&#039;устойчивым&#039;&#039;]], так как результат работы зависит от порядка чтения транзакций и от текущего набора транзакций в кластере.&lt;br /&gt;
* Выполняется свойство сбалансированности операций между параллельными ветвями алгоритма, так как для каждой транзакции выполняются функции DeltaAdd/DeltaRemove, считающие стоимость добавления/удаления транзакции.&lt;br /&gt;
* Свойство [[глоссарий#Детерминированность|&#039;&#039;детерминированности алгоритмов&#039;&#039;]] не выполняется, так как результат алгоритма зависит от порядка прохождения транзакций. Но если рассматривать транзакции как нумерованный список, то результат будет определен однозначно от запуска к запуску. Однако существует расширение алгоритма, обеспечивающее свойство детерминированности. &amp;lt;ref&amp;gt;Li, Y., Le, J., Wang, M. Improving CLOPE’s Profit Value and Stability with an Optimized Agglomerative Approach. Algorithms 2015, 8, 380-394.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
* Так как алгоритм предназначен для кластеризации категориальных данных, то он практически неприменим для числовой кластеризации.&lt;br /&gt;
* Быстро работает даже для большого количества данных, обеспечивая при этом хорошее качество кластеризации&lt;br /&gt;
* Имеет простую реализацию&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
Проверка масштабируемости проводилась на суперкомпьютере &amp;quot;Ломоносов&amp;quot; с числом процессоров 1, 8, 16, 32 и 64 на десяти различных сетках - от 1000×1000 до 10000×10000. Для компиляции программы использовался компилятор Intel(13.1.0) с OpenMPI(1.8.4). Результаты проверки на графике ниже.&lt;br /&gt;
&lt;br /&gt;
[[file:Graf_lom.png||700px]]&lt;br /&gt;
&lt;br /&gt;
Таким образом, можно сделать вывод о том, что алгоритм кластеризации CLOPE является масштабируемым.&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
* http://weka.sourceforge.net/doc.stable/weka/clusterers/CLOPE.html - реализация в open source библиотеке для анализа данных WEKA(Waikato Environment for Knowledge Analysis) на языке Java&lt;br /&gt;
Также существуют пользовательские реализации алгоритма:&lt;br /&gt;
* https://github.com/infozor/php_mysql_clustering_clope - реализация алгоритма на PHP&lt;br /&gt;
* https://github.com/Tolsi/scala-clope - реализация алгоритма Scala&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:%D0%9F%D0%B0%D0%B2%D0%B5%D0%BB/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BA%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D0%B9%D0%BD%D1%8B%D1%85_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85_CLOPE&amp;diff=21605</id>
		<title>Участник:Павел/Алгоритм кластеризации категорийных данных CLOPE</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9F%D0%B0%D0%B2%D0%B5%D0%BB/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BA%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D0%B9%D0%BD%D1%8B%D1%85_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85_CLOPE&amp;diff=21605"/>
		<updated>2017-01-19T15:33:31Z</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;
Алгоритм CLOPE (Clustering with sLOPE&amp;lt;ref&amp;gt;Yang, Y., Guan, H., You. J. CLOPE: A fast and Effective Clustering Algorithm for Transactional Data In Proc. of SIGKDD’02, July 23-26, 2002, Edmonton, Alberta, Canada.&amp;lt;/ref&amp;gt;) неирархический метод кластеризации, предназначенный для кластеризации огромных наборов категорийных данных. К достоинствам алгоритма относятся высокие масштабируемость и скорость работы и качество кластеризации, что достигается использованием глобального критерия оптимизации на основе максимизации градиента высоты гистограммы кластера. Отличается простотой программной реализации. &lt;br /&gt;
&lt;br /&gt;
Во время работы алгоритм хранит в памяти небольшое количество информации по каждому кластеру и требует минимальное число сканирований набора данных. CLOPE автоматически подбирает количество кластеров, причем это регулируется одним единственным параметром - коэффициентом отталкивания &amp;lt;math&amp;gt; r &amp;lt;/math&amp;gt;. При этом он обеспечивает более высокую производительность и лучшее качество кластеризации в сравнении с многими иерархическими алгоритмами.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
Пусть имеется база транзакций &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, состоящая из множества транзакций &amp;lt;math&amp;gt;\{t_1,t_2,...,t_n\}&amp;lt;/math&amp;gt;. Каждая транзакция есть набор объектов &amp;lt;math&amp;gt;\{i_1,...,i_m\}&amp;lt;/math&amp;gt;. Множество кластеров &amp;lt;math&amp;gt;\{C_1,...,C_k\}&amp;lt;/math&amp;gt; есть разбиение множества &amp;lt;math&amp;gt;\{t_1,...,t_n\}&amp;lt;/math&amp;gt;, такое, что &amp;lt;math&amp;gt;C_1 \cup \dots \cup C_k=\{t_1,...,t_n\}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_i \ne \empty&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_i \cap C_j = \empty &amp;lt;/math&amp;gt;, для &amp;lt;math&amp;gt;i \ge 1, k \ge j&amp;lt;/math&amp;gt;. Каждый элемент &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; называется кластером, а &amp;lt;math&amp;gt;n, m, k&amp;lt;/math&amp;gt; – количество транзакций, количество объектов в базе транзакций и число кластеров соответственно.&lt;br /&gt;
&lt;br /&gt;
Каждый кластер &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; имеет следующие характеристики:&lt;br /&gt;
&amp;lt;math&amp;gt;D(C)&amp;lt;/math&amp;gt; – множество уникальных объектов;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;Occ(i,C)&amp;lt;/math&amp;gt; – количество вхождений (частота) объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; в кластер &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;S(C)= \sum_{i \in D(C)} Occ(i,C)= \sum_{t_i \in C}  \mid t_i  \mid , &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;W(C)=  \mid D(C) \mid ,H(C)=S(C)/W(C) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Функция стоимости:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; Profit(C) = \frac{\sum^{k}_{i=1} G(C_i) \times \mid C_i \mid} {\sum^{k}_{i=1} \mid C_i \mid } = \frac{\sum^{k}_{i=1} \frac{S(C_i)}{W(C_i)^r} \times \mid C_i \mid} {\sum^{k}_{i=1} \mid C_i \mid }  &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;\mid C_i \mid&amp;lt;/math&amp;gt;  количество объектов в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом кластере, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; – количество кластеров, &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; – коэффициент отталкивания &amp;lt;math&amp;gt;(0 &amp;lt; r \le 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С помощью параметра &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; регулируется уровень сходства транзакций внутри кластера, и, как&lt;br /&gt;
следствие, финальное количество кластеров. Этот коэффициент подбирается пользователем. Чем больше &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt;, тем ниже уровень сходства и тем больше кластеров будет сгенерировано.&lt;br /&gt;
&lt;br /&gt;
Постановка задачи кластеризации алгоритмом CLOPE выглядит следующим образом: &lt;br /&gt;
&lt;br /&gt;
для заданных &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; найти разбиение &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; такое, что: &lt;br /&gt;
&amp;lt;math&amp;gt;Profit(C) \longrightarrow max &amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит в вычислении на каждой итерации стоимости добавления и удаления транзакции из кластера: &lt;br /&gt;
&lt;br /&gt;
*вычисление нового размера кластера &amp;lt;math&amp;gt;S_{new}(C_i)=S(C_i) \pm \mid(t_n)\mid &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\mid(t_n)\mid&amp;lt;/math&amp;gt; - длина транзакции&lt;br /&gt;
&lt;br /&gt;
*вычисление новой ширины кластера &amp;lt;math&amp;gt;W_{new}(C_i)=\mid D(C_i \cup t_n)|&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*вычисление стоимости &amp;lt;math&amp;gt;\frac{S_{new}(C_i)(\mid C_i \mid \pm 1)}{W_{new}(C_i)^r} - \frac{S(C_i) \mid C_i \mid }{W(C_i)^r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм состоит из следующих этапов:&lt;br /&gt;
&lt;br /&gt;
1. &#039;&#039;&#039;Инициализация&#039;&#039;&#039;. На этом этапе происходит первый проход по таблице с транзакциями для построения начального разбиения, для каждой транзакции определяется кластер исходя из максимизации стоимости.&lt;br /&gt;
&lt;br /&gt;
2. &#039;&#039;&#039;Итерация&#039;&#039;&#039;. На данном этапе для каждой транзакции проводится попытка перемещения в другой кластер для максимизации функции стоимости.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
[[File:InitIter.PNG||500px]]&lt;br /&gt;
&lt;br /&gt;
Первая часть алгоритма - инициализация: для каждой транзакции вычисляется кластер, к которому она будет отнесена исходя из максимизации функции стоимости. Для этого вычисляется вспомогательная функция DeltaAdd, которая считает стоимость добавления транзакции к одному из существующих кластеров, либо к пустому. В итоге транзакция помещается в кластер, для которого цена добавления максимальна.&lt;br /&gt;
&lt;br /&gt;
Вторая часть алгоритма - уточняющие итерации: здесь происходит попытка улучшить вычисленные на первом этапе кластеры. В каждой итерации происходит перебор всех транзакций, и для каждой транзакции вычисляется цена удаления ее из текущего кластера и цена добавления в другой кластер. Суммарная стоимость перемещения будет являться суммой стоимостей удаления и добавления. Если максимальная стоимость перемещения данной транзакции в какой-либо больше нуля, то она перемещается в этот кластер. &lt;br /&gt;
&lt;br /&gt;
Вычисления происходят до тех пор, пока за итерацию происходит хотя бы одно перемещение транзакции. Если за итерацию не было произведено ни одного перемещения, то текущее состояние кластеров является устойчивым и оптимальным. &amp;lt;ref&amp;gt;Павлин Н. Кластеризация категорийных данных: масштабируемый алгоритм CLOPE, https://basegroup.ru/community/articles/clope&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Схема реализации на псевдокоде:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Входные параметры:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - транзакции&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; - коэффициент отталкивания&lt;br /&gt;
&lt;br /&gt;
Выходной параметр:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; кластеры, в начале алгоритма - пустое множество&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация:&#039;&#039;&#039;&lt;br /&gt;
    &#039;&#039;&#039;for&#039;&#039;&#039; t_i in t:&lt;br /&gt;
    max = 0&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; C_j in C:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; DeltaAdd(C_j,t_i,r) &amp;gt; max:&lt;br /&gt;
                max = DeltaAdd(C_j,t_i,r)&lt;br /&gt;
                C_best = C_j&lt;br /&gt;
    &#039;&#039;&#039;put&#039;&#039;&#039; t_i in C_best&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Итерации:&#039;&#039;&#039;&lt;br /&gt;
    move = True&lt;br /&gt;
    &#039;&#039;&#039;while&#039;&#039;&#039; move == True:&lt;br /&gt;
    move = False&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; t_i in t:&lt;br /&gt;
            max = 0&lt;br /&gt;
            C_now = t_i.cluster&lt;br /&gt;
            removeCost = DeltaRemove(C_now,t_i,r)&lt;br /&gt;
            &#039;&#039;&#039;for&#039;&#039;&#039; C_j in C:&lt;br /&gt;
                &#039;&#039;&#039;if&#039;&#039;&#039; DeltaAdd(C_j,t_i,r) + removeCost &amp;gt; max:&lt;br /&gt;
                    max = DeltaAdd(C_j,t_i,r) + removeCost&lt;br /&gt;
                    C_best = C_j&lt;br /&gt;
        if max &amp;gt; 0&lt;br /&gt;
            &#039;&#039;&#039;del&#039;&#039;&#039; t_i from C_now&lt;br /&gt;
            &#039;&#039;&#039;put&#039;&#039;&#039; t_i in C_best&lt;br /&gt;
            move = True&lt;br /&gt;
&lt;br /&gt;
Вспомогательная функция &#039;&#039;&#039;DeltaAdd&#039;&#039;&#039;:&lt;br /&gt;
    &#039;&#039;&#039;function&#039;&#039;&#039; DeltaAdd(C,t,r)&lt;br /&gt;
        S_new=C.size + t.itemCount&lt;br /&gt;
        W_new=C.wigth&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; item in t_i:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; C_j.occ(item) = 0&lt;br /&gt;
                &#039;&#039;W_new = W_new + 1&lt;br /&gt;
        &#039;&#039;&#039;return&#039;&#039;&#039; S_new * (C.count+1) / (W_new ^ r) - (C.size * C.count) / (C.wigth ^ r)&lt;br /&gt;
&lt;br /&gt;
Вспомогательная функция &#039;&#039;&#039;DeltaRemove&#039;&#039;&#039;:&lt;br /&gt;
    &#039;&#039;&#039;function&#039;&#039;&#039; DeltaRemove(C,t,r)&lt;br /&gt;
        S_new=C.size - t.itemCount&lt;br /&gt;
        W_new=C.wigth&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; item in t:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; C_j.occ(item) = 1&lt;br /&gt;
                &#039;&#039;W_new = W_new - 1&lt;br /&gt;
        &#039;&#039;&#039;return&#039;&#039;&#039; S_new * (C.count-1) / (W_new ^ r) - (C.size * C.count) / (C.wigth ^ r)&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
В соответствии с ранее введенным обозначением &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - количество транзакций, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина транзакции(максимальная), &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество кластеров.&lt;br /&gt;
&lt;br /&gt;
Основные вычисления восполняются в функции DeltaAdd/DeltaRemove: производится 1 сложение, не более &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; сложений/вычитаний, 2 умножения, 2 деления, 2 возведения в степень и 1 сложение - итого &amp;lt;math&amp;gt;m + 8&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;k&amp;lt;/math&amp;gt; штук). Итого выполняется &amp;lt;math&amp;gt;n*k*(m+8)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
В добавок к этому при добавлении/удалении транзакции к кластеру производится пересчет его характеристик: &amp;lt;math&amp;gt;m+2&amp;lt;/math&amp;gt; операции.&lt;br /&gt;
&lt;br /&gt;
Из того можно сделать вывод, что оценка сложность алгоритма равна &amp;lt;math&amp;gt;O(n*k*m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
&lt;br /&gt;
На рисунке ниже представлена схема этапа инициализации на примере входной транзакции &#039;&#039;&#039;T&#039;&#039;&#039; и четырех кластеров &#039;&#039;&#039;Cl 1&#039;&#039;&#039;, &#039;&#039;&#039;Cl 2&#039;&#039;&#039;, &#039;&#039;&#039;Cl 3&#039;&#039;&#039; и &#039;&#039;&#039;Cl 4&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Объект &#039;&#039;&#039;DeltaAdd&#039;&#039;&#039; соответствует выполнению соответствующей функции для вычисления цены добавления транзакции на кластер. После выполнения всех &#039;&#039;&#039;DeltaAdd&#039;&#039;&#039; для одной транзакции выполняется определение максимального значения функции и выбор кластера, на который будет помещена транзакция. На этапе инициализации при обработке каждой транзакции количество кластеров может как увеличиться, так и остаться неизменным.&lt;br /&gt;
&lt;br /&gt;
[[File:InitDef.PNG||700px]]&lt;br /&gt;
&lt;br /&gt;
Этап итераций отличается только тем, что на нем дополнительно считается функция &#039;&#039;&#039;DeltaRemove&#039;&#039;&#039; вычисления стоимости удаления транзакции с кластера. На этапе итерации функции DeltaAdd/DeltaRemove могут считать параллельно для каждой транзакции.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Вычисление стоимости добавления/удаления транзакции, которые выполняются функциями DeltaAdd/DeltaRemove, происходит независимо для всех &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; кластеров. Поэтому все вычисления можно производить параллельно. Таким образом сложность алгоритма с &amp;lt;math&amp;gt;O(n*k*m)&amp;lt;/math&amp;gt; понижается до &amp;lt;math&amp;gt;O(n*m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; транзакций длины &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; и коэффициент отталкивания &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
метки классов для каждой транзакции в соответствии с проведенной кластеризацией(числовая последовательность длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной сложности алгоритма определяется количеством кластеров: &amp;lt;math&amp;gt;\dfrac{O(n*k*m)}{O(n*m)} = k&amp;lt;/math&amp;gt;&lt;br /&gt;
* [[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]] алгоритма равна &amp;lt;math&amp;gt;\dfrac{nk(m+8) + m + 2}{nm + n + 1} \cong k&amp;lt;/math&amp;gt;&lt;br /&gt;
* Алгоритм не является [[глоссарий#Устойчивость|&#039;&#039;устойчивым&#039;&#039;]], так как результат работы зависит от порядка чтения транзакций и от текущего набора транзакций в кластере.&lt;br /&gt;
* Выполняется свойство сбалансированности операций между параллельными ветвями алгоритма, так как для каждой транзакции выполняются функции DeltaAdd/DeltaRemove, считающие стоимость добавления/удаления транзакции.&lt;br /&gt;
* Свойство [[глоссарий#Детерминированность|&#039;&#039;детерминированности алгоритмов&#039;&#039;]] не выполняется, так как результат алгоритма зависит от порядка прохождения транзакций. Но если рассматривать транзакции как нумерованный список, то результат будет определен однозначно от запуска к запуску. Однако существует расширение алгоритма, обеспечивающее свойство детерминированности. &amp;lt;ref&amp;gt;Li, Y., Le, J., Wang, M. Improving CLOPE’s Profit Value and Stability with an Optimized Agglomerative Approach. Algorithms 2015, 8, 380-394.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
* Так как алгоритм предназначен для кластеризации категориальных данных, то он практически неприменим для числовой кластеризации.&lt;br /&gt;
* Быстро работает даже для большого количества данных, обеспечивая при этом хорошее качество кластеризации&lt;br /&gt;
* Имеет простую реализацию&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
Проверка масштабируемости проводилась на суперкомпьютере &amp;quot;Ломоносов&amp;quot; с числом процессоров 1, 8, 16, 32 и 64 на десяти различных сетках - от 1000×1000 до 10000×10000. Для компиляции программы использовался компилятор Intel(13.1.0) с OpenMPI(1.8.4). Результаты проверки на графике ниже.&lt;br /&gt;
&lt;br /&gt;
[[file:Graf_lom.png||700px]]&lt;br /&gt;
&lt;br /&gt;
Таким образом, можно сделать вывод о том, что алгоритм кластеризации CLOPE является масштабируемым.&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
* http://weka.sourceforge.net/doc.stable/weka/clusterers/CLOPE.html - реализация в open source библиотеке для анализа данных WEKA(Waikato Environment for Knowledge Analysis) на языке Java&lt;br /&gt;
Также существуют пользовательские реализации алгоритма:&lt;br /&gt;
* https://github.com/infozor/php_mysql_clustering_clope - реализация алгоритма на PHP&lt;br /&gt;
* https://github.com/Tolsi/scala-clope - реализация алгоритма Scala&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:%D0%9F%D0%B0%D0%B2%D0%B5%D0%BB/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BA%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D0%B9%D0%BD%D1%8B%D1%85_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85_CLOPE&amp;diff=21604</id>
		<title>Участник:Павел/Алгоритм кластеризации категорийных данных CLOPE</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9F%D0%B0%D0%B2%D0%B5%D0%BB/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BA%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D0%B9%D0%BD%D1%8B%D1%85_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85_CLOPE&amp;diff=21604"/>
		<updated>2017-01-19T15:32:00Z</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;
Алгоритм CLOPE (Clustering with sLOPE&amp;lt;ref&amp;gt;Yang, Y., Guan, H., You. J. CLOPE: A fast and Effective Clustering Algorithm for Transactional Data In Proc. of SIGKDD’02, July 23-26, 2002, Edmonton, Alberta, Canada.&amp;lt;/ref&amp;gt;) неирархический метод кластеризации, предназначенный для кластеризации огромных наборов категорийных данных. К достоинствам алгоритма относятся высокие масштабируемость и скорость работы и качество кластеризации, что достигается использованием глобального критерия оптимизации на основе максимизации градиента высоты гистограммы кластера. Отличается простотой программной реализации. &lt;br /&gt;
&lt;br /&gt;
Во время работы алгоритм хранит в памяти небольшое количество информации по каждому кластеру и требует минимальное число сканирований набора данных. CLOPE автоматически подбирает количество кластеров, причем это регулируется одним единственным параметром - коэффициентом отталкивания &amp;lt;math&amp;gt; r &amp;lt;/math&amp;gt;. При этом он обеспечивает более высокую производительность и лучшее качество кластеризации в сравнении с многими иерархическими алгоритмами.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
Пусть имеется база транзакций &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, состоящая из множества транзакций &amp;lt;math&amp;gt;\{t_1,t_2,...,t_n\}&amp;lt;/math&amp;gt;. Каждая транзакция есть набор объектов &amp;lt;math&amp;gt;\{i_1,...,i_m\}&amp;lt;/math&amp;gt;. Множество кластеров &amp;lt;math&amp;gt;\{C_1,...,C_k\}&amp;lt;/math&amp;gt; есть разбиение множества &amp;lt;math&amp;gt;\{t_1,...,t_n\}&amp;lt;/math&amp;gt;, такое, что &amp;lt;math&amp;gt;C_1 \cup \dots \cup C_k=\{t_1,...,t_n\}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_i \ne \empty&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_i \cap C_j = \empty &amp;lt;/math&amp;gt;, для &amp;lt;math&amp;gt;i \ge 1, k \ge j&amp;lt;/math&amp;gt;. Каждый элемент &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; называется кластером, а &amp;lt;math&amp;gt;n, m, k&amp;lt;/math&amp;gt; – количество транзакций, количество объектов в базе транзакций и число кластеров соответственно.&lt;br /&gt;
&lt;br /&gt;
Каждый кластер &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; имеет следующие характеристики:&lt;br /&gt;
&amp;lt;math&amp;gt;D(C)&amp;lt;/math&amp;gt; – множество уникальных объектов;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;Occ(i,C)&amp;lt;/math&amp;gt; – количество вхождений (частота) объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; в кластер &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;S(C)= \sum_{i \in D(C)} Occ(i,C)= \sum_{t_i \in C}  \mid t_i  \mid , &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;W(C)=  \mid D(C) \mid ,H(C)=S(C)/W(C) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Функция стоимости:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; Profit(C) = \frac{\sum^{k}_{i=1} G(C_i) \times \mid C_i \mid} {\sum^{k}_{i=1} \mid C_i \mid } = \frac{\sum^{k}_{i=1} \frac{S(C_i)}{W(C_i)^r} \times \mid C_i \mid} {\sum^{k}_{i=1} \mid C_i \mid }  &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;\mid C_i \mid&amp;lt;/math&amp;gt;  количество объектов в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом кластере, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; – количество кластеров, &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; – коэффициент отталкивания &amp;lt;math&amp;gt;(0 &amp;lt; r \le 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С помощью параметра &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; регулируется уровень сходства транзакций внутри кластера, и, как&lt;br /&gt;
следствие, финальное количество кластеров. Этот коэффициент подбирается пользователем. Чем больше &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt;, тем ниже уровень сходства и тем больше кластеров будет сгенерировано.&lt;br /&gt;
&lt;br /&gt;
Постановка задачи кластеризации алгоритмом CLOPE выглядит следующим образом: &lt;br /&gt;
&lt;br /&gt;
для заданных &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; найти разбиение &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; такое, что: &lt;br /&gt;
&amp;lt;math&amp;gt;Profit(C) \longrightarrow max &amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит в вычислении на каждой итерации стоимости добавления и удаления транзакции из кластера: &lt;br /&gt;
&lt;br /&gt;
*вычисление нового размера кластера &amp;lt;math&amp;gt;S_{new}(C_i)=S(C_i) \pm \mid(t_n)\mid &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\mid(t_n)\mid&amp;lt;/math&amp;gt; - длина транзакции&lt;br /&gt;
&lt;br /&gt;
*вычисление новой ширины кластера &amp;lt;math&amp;gt;W_{new}(C_i)=\mid D(C_i \cup t_n)|&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*вычисление стоимости &amp;lt;math&amp;gt;\frac{S_{new}(C_i)(\mid C_i \mid \pm 1)}{W_{new}(C_i)^r} - \frac{S(C_i) \mid C_i \mid }{W(C_i)^r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм состоит из следующих этапов:&lt;br /&gt;
&lt;br /&gt;
1. &#039;&#039;&#039;Инициализация&#039;&#039;&#039;. На этом этапе происходит первый проход по таблице с транзакциями для построения начального разбиения, для каждой транзакции определяется кластер исходя из максимизации стоимости.&lt;br /&gt;
&lt;br /&gt;
2. &#039;&#039;&#039;Итерация&#039;&#039;&#039;. На данном этапе для каждой транзакции проводится попытка перемещения в другой кластер для максимизации функции стоимости.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
[[File:InitIter.PNG||500px]]&lt;br /&gt;
&lt;br /&gt;
Первая часть алгоритма - инициализация: для каждой транзакции вычисляется кластер, к которому она будет отнесена исходя из максимизации функции стоимости. Для этого вычисляется вспомогательная функция DeltaAdd, которая считает стоимость добавления транзакции к одному из существующих кластеров, либо к пустому. В итоге транзакция помещается в кластер, для которого цена добавления максимальна.&lt;br /&gt;
&lt;br /&gt;
Вторая часть алгоритма - уточняющие итерации: здесь происходит попытка улучшить вычисленные на первом этапе кластеры. В каждой итерации происходит перебор всех транзакций, и для каждой транзакции вычисляется цена удаления ее из текущего кластера и цена добавления в другой кластер. Суммарная стоимость перемещения будет являться суммой стоимостей удаления и добавления. Если максимальная стоимость перемещения данной транзакции в какой-либо больше нуля, то она перемещается в этот кластер. &lt;br /&gt;
&lt;br /&gt;
Вычисления происходят до тех пор, пока за итерацию происходит хотя бы одно перемещение транзакции. Если за итерацию не было произведено ни одного перемещения, то текущее состояние кластеров является устойчивым и оптимальным. &amp;lt;ref&amp;gt;Павлин Н. Кластеризация категорийных данных: масштабируемый алгоритм CLOPE, https://basegroup.ru/community/articles/clope&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Схема реализации на псевдокоде:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Входные параметры:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - транзакции&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; - коэффициент отталкивания&lt;br /&gt;
&lt;br /&gt;
Выходной параметр:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; кластеры, в начале алгоритма - пустое множество&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация:&#039;&#039;&#039;&lt;br /&gt;
    &#039;&#039;&#039;for&#039;&#039;&#039; t_i in t:&lt;br /&gt;
    max = 0&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; C_j in C:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; DeltaAdd(C_j,t_i,r) &amp;gt; max:&lt;br /&gt;
                max = DeltaAdd(C_j,t_i,r)&lt;br /&gt;
                C_best = C_j&lt;br /&gt;
    &#039;&#039;&#039;put&#039;&#039;&#039; t_i in C_best&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Итерации:&#039;&#039;&#039;&lt;br /&gt;
    move = True&lt;br /&gt;
    &#039;&#039;&#039;while&#039;&#039;&#039; move == True:&lt;br /&gt;
    move = False&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; t_i in t:&lt;br /&gt;
            max = 0&lt;br /&gt;
            C_now = t_i.cluster&lt;br /&gt;
            removeCost = DeltaRemove(C_now,t_i,r)&lt;br /&gt;
            &#039;&#039;&#039;for&#039;&#039;&#039; C_j in C:&lt;br /&gt;
                &#039;&#039;&#039;if&#039;&#039;&#039; DeltaAdd(C_j,t_i,r) + removeCost &amp;gt; max:&lt;br /&gt;
                    max = DeltaAdd(C_j,t_i,r) + removeCost&lt;br /&gt;
                    C_best = C_j&lt;br /&gt;
        if max &amp;gt; 0&lt;br /&gt;
            &#039;&#039;&#039;del&#039;&#039;&#039; t_i from C_now&lt;br /&gt;
            &#039;&#039;&#039;put&#039;&#039;&#039; t_i in C_best&lt;br /&gt;
            move = True&lt;br /&gt;
&lt;br /&gt;
Вспомогательная функция &#039;&#039;&#039;DeltaAdd&#039;&#039;&#039;:&lt;br /&gt;
    &#039;&#039;&#039;function&#039;&#039;&#039; DeltaAdd(C,t,r)&lt;br /&gt;
        S_new=C.size + t.itemCount&lt;br /&gt;
        W_new=C.wigth&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; item in t_i:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; C_j.occ(item) = 0&lt;br /&gt;
                &#039;&#039;W_new = W_new + 1&lt;br /&gt;
        &#039;&#039;&#039;return&#039;&#039;&#039; S_new * (C.count+1) / (W_new ^ r) - (C.size * C.count) / (C.wigth ^ r)&lt;br /&gt;
&lt;br /&gt;
Вспомогательная функция &#039;&#039;&#039;DeltaRemove&#039;&#039;&#039;:&lt;br /&gt;
    &#039;&#039;&#039;function&#039;&#039;&#039; DeltaRemove(C,t,r)&lt;br /&gt;
        S_new=C.size - t.itemCount&lt;br /&gt;
        W_new=C.wigth&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; item in t:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; C_j.occ(item) = 1&lt;br /&gt;
                &#039;&#039;W_new = W_new - 1&lt;br /&gt;
        &#039;&#039;&#039;return&#039;&#039;&#039; S_new * (C.count-1) / (W_new ^ r) - (C.size * C.count) / (C.wigth ^ r)&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
В соответствии с ранее введенным обозначением &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - количество транзакций, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина транзакции(максимальная), &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество кластеров.&lt;br /&gt;
&lt;br /&gt;
Основные вычисления восполняются в функции DeltaAdd/DeltaRemove: производится 1 сложение, не более &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; сложений/вычитаний, 2 умножения, 2 деления, 2 возведения в степень и 1 сложение - итого &amp;lt;math&amp;gt;m + 8&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;k&amp;lt;/math&amp;gt; штук). Итого выполняется &amp;lt;math&amp;gt;n*k*(m+8)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
В добавок к этому при добавлении/удалении транзакции к кластеру производится пересчет его характеристик: &amp;lt;math&amp;gt;m+2&amp;lt;/math&amp;gt; операции.&lt;br /&gt;
&lt;br /&gt;
Из того можно сделать вывод, что оценка сложность алгоритма равна &amp;lt;math&amp;gt;O(n*k*m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
&lt;br /&gt;
На рисунке ниже представлена схема этапа инициализации на примере входной транзакции &#039;&#039;&#039;T&#039;&#039;&#039; и четырех кластеров &#039;&#039;&#039;Cl 1&#039;&#039;&#039;, &#039;&#039;&#039;Cl 2&#039;&#039;&#039;, &#039;&#039;&#039;Cl 3&#039;&#039;&#039; и &#039;&#039;&#039;Cl 4&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Объект &#039;&#039;&#039;DeltaAdd&#039;&#039;&#039; соответствует выполнению соответствующей функции для вычисления цены добавления транзакции на кластер. После выполнения всех &#039;&#039;&#039;DeltaAdd&#039;&#039;&#039; для одной транзакции выполняется определение максимального значения функции и выбор кластера, на который будет помещена транзакция. На этапе инициализации при обработке каждой транзакции количество кластеров может как увеличиться, так и остаться неизменным.&lt;br /&gt;
&lt;br /&gt;
[[File:InitDef.PNG||700px]]&lt;br /&gt;
&lt;br /&gt;
Этап итераций отличается только тем, что на нем дополнительно считается функция &#039;&#039;&#039;DeltaRemove&#039;&#039;&#039; вычисления стоимости удаления транзакции с кластера. На этапе итерации функции DeltaAdd/DeltaRemove могут считать параллельно для каждой транзакции.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Вычисление стоимости добавления/удаления транзакции, которые выполняются функциями DeltaAdd/DeltaRemove, происходит независимо для всех &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; кластеров. Поэтому все вычисления можно производить параллельно. Таким образом сложность алгоритма с &amp;lt;math&amp;gt;O(n*k*m)&amp;lt;/math&amp;gt; понижается до &amp;lt;math&amp;gt;O(n*m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; транзакций длины &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; и коэффициент отталкивания &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
метки классов для каждой транзакции в соответствии с проведенной кластеризацией(числовая последовательность длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной сложности алгоритма определяется количеством кластеров: &amp;lt;math&amp;gt;\dfrac{O(n*k*m)}{O(n*m)} = k&amp;lt;/math&amp;gt;&lt;br /&gt;
* [[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]] алгоритма равна &amp;lt;math&amp;gt;\dfrac{nk(m+8) + m + 2}{nm + n + 1} \cong k&amp;lt;/math&amp;gt;&lt;br /&gt;
* Алгоритм не является [[глоссарий#Устойчивость|&#039;&#039;устойчивым&#039;&#039;]], так как результат работы зависит от порядка чтения транзакций и от текущего набора транзакций в кластере.&lt;br /&gt;
* Выполняется свойство сбалансированности операций между параллельными ветвями алгоритма, так как для каждой транзакции выполняются функции DeltaAdd/DeltaRemove, считающие стоимость добавления/удаления транзакции.&lt;br /&gt;
* Свойство [[глоссарий#Детерминированность|&#039;&#039;детерминированности алгоритмов&#039;&#039;]] не выполняется, так как результат алгоритма зависит от порядка прохождения транзакций. Но если рассматривать транзакции как нумерованный список, то результат будет определен однозначно от запуска к запуску. Однако существует расширение алгоритма, обеспечивающее свойство детерминированности. &amp;lt;ref&amp;gt;Li, Y., Le, J., Wang, M. Improving CLOPE’s Profit Value and Stability with an Optimized Agglomerative Approach. Algorithms 2015, 8, 380-394.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
* Так как алгоритм предназначен для кластеризации категориальных данных, то он практически неприменим для числовой кластеризации.&lt;br /&gt;
* Быстро работает даже для большого количества данных, обеспечивая при этом хорошее качество кластеризации&lt;br /&gt;
* Имеет простую реализацию&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
Проверка масштабируемости проводилась на суперкомпьютере &amp;quot;Ломоносов&amp;quot; с числом процессоров 1, 8, 16, 32 и 64 на десяти различных сетках - от 1000×1000 до 10000×10000. Для компиляции использовался компилятор Intel(13.1.0) с OpenMPI(1.8.4). Результаты проверки на графике ниже.&lt;br /&gt;
&lt;br /&gt;
[[file:Graf_lom.png||700px]]&lt;br /&gt;
&lt;br /&gt;
Таким образом, можно сделать вывод о том, что алгоритм кластеризации CLOPE является масштабируемым.&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
* http://weka.sourceforge.net/doc.stable/weka/clusterers/CLOPE.html - реализация в open source библиотеке для анализа данных WEKA(Waikato Environment for Knowledge Analysis) на языке Java&lt;br /&gt;
Также существуют пользовательские реализации алгоритма:&lt;br /&gt;
* https://github.com/infozor/php_mysql_clustering_clope - реализация алгоритма на PHP&lt;br /&gt;
* https://github.com/Tolsi/scala-clope - реализация алгоритма Scala&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:%D0%9F%D0%B0%D0%B2%D0%B5%D0%BB/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BA%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D0%B9%D0%BD%D1%8B%D1%85_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85_CLOPE&amp;diff=21603</id>
		<title>Участник:Павел/Алгоритм кластеризации категорийных данных CLOPE</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9F%D0%B0%D0%B2%D0%B5%D0%BB/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BA%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D0%B9%D0%BD%D1%8B%D1%85_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85_CLOPE&amp;diff=21603"/>
		<updated>2017-01-19T15:12:57Z</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;
Алгоритм CLOPE (Clustering with sLOPE&amp;lt;ref&amp;gt;Yang, Y., Guan, H., You. J. CLOPE: A fast and Effective Clustering Algorithm for Transactional Data In Proc. of SIGKDD’02, July 23-26, 2002, Edmonton, Alberta, Canada.&amp;lt;/ref&amp;gt;) неирархический метод кластеризации, предназначенный для кластеризации огромных наборов категорийных данных. К достоинствам алгоритма относятся высокие масштабируемость и скорость работы и качество кластеризации, что достигается использованием глобального критерия оптимизации на основе максимизации градиента высоты гистограммы кластера. Отличается простотой программной реализации. &lt;br /&gt;
&lt;br /&gt;
Во время работы алгоритм хранит в памяти небольшое количество информации по каждому кластеру и требует минимальное число сканирований набора данных. CLOPE автоматически подбирает количество кластеров, причем это регулируется одним единственным параметром - коэффициентом отталкивания &amp;lt;math&amp;gt; r &amp;lt;/math&amp;gt;. При этом он обеспечивает более высокую производительность и лучшее качество кластеризации в сравнении с многими иерархическими алгоритмами.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
Пусть имеется база транзакций &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, состоящая из множества транзакций &amp;lt;math&amp;gt;\{t_1,t_2,...,t_n\}&amp;lt;/math&amp;gt;. Каждая транзакция есть набор объектов &amp;lt;math&amp;gt;\{i_1,...,i_m\}&amp;lt;/math&amp;gt;. Множество кластеров &amp;lt;math&amp;gt;\{C_1,...,C_k\}&amp;lt;/math&amp;gt; есть разбиение множества &amp;lt;math&amp;gt;\{t_1,...,t_n\}&amp;lt;/math&amp;gt;, такое, что &amp;lt;math&amp;gt;C_1 \cup \dots \cup C_k=\{t_1,...,t_n\}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_i \ne \empty&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_i \cap C_j = \empty &amp;lt;/math&amp;gt;, для &amp;lt;math&amp;gt;i \ge 1, k \ge j&amp;lt;/math&amp;gt;. Каждый элемент &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; называется кластером, а &amp;lt;math&amp;gt;n, m, k&amp;lt;/math&amp;gt; – количество транзакций, количество объектов в базе транзакций и число кластеров соответственно.&lt;br /&gt;
&lt;br /&gt;
Каждый кластер &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; имеет следующие характеристики:&lt;br /&gt;
&amp;lt;math&amp;gt;D(C)&amp;lt;/math&amp;gt; – множество уникальных объектов;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;Occ(i,C)&amp;lt;/math&amp;gt; – количество вхождений (частота) объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; в кластер &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;S(C)= \sum_{i \in D(C)} Occ(i,C)= \sum_{t_i \in C}  \mid t_i  \mid , &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;W(C)=  \mid D(C) \mid ,H(C)=S(C)/W(C) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Функция стоимости:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; Profit(C) = \frac{\sum^{k}_{i=1} G(C_i) \times \mid C_i \mid} {\sum^{k}_{i=1} \mid C_i \mid } = \frac{\sum^{k}_{i=1} \frac{S(C_i)}{W(C_i)^r} \times \mid C_i \mid} {\sum^{k}_{i=1} \mid C_i \mid }  &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;\mid C_i \mid&amp;lt;/math&amp;gt;  количество объектов в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом кластере, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; – количество кластеров, &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; – коэффициент отталкивания &amp;lt;math&amp;gt;(0 &amp;lt; r \le 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С помощью параметра &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; регулируется уровень сходства транзакций внутри кластера, и, как&lt;br /&gt;
следствие, финальное количество кластеров. Этот коэффициент подбирается пользователем. Чем больше &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt;, тем ниже уровень сходства и тем больше кластеров будет сгенерировано.&lt;br /&gt;
&lt;br /&gt;
Постановка задачи кластеризации алгоритмом CLOPE выглядит следующим образом: &lt;br /&gt;
&lt;br /&gt;
для заданных &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; найти разбиение &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; такое, что: &lt;br /&gt;
&amp;lt;math&amp;gt;Profit(C) \longrightarrow max &amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит в вычислении на каждой итерации стоимости добавления и удаления транзакции из кластера: &lt;br /&gt;
&lt;br /&gt;
*вычисление нового размера кластера &amp;lt;math&amp;gt;S_{new}(C_i)=S(C_i) \pm \mid(t_n)\mid &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\mid(t_n)\mid&amp;lt;/math&amp;gt; - длина транзакции&lt;br /&gt;
&lt;br /&gt;
*вычисление новой ширины кластера &amp;lt;math&amp;gt;W_{new}(C_i)=\mid D(C_i \cup t_n)|&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*вычисление стоимости &amp;lt;math&amp;gt;\frac{S_{new}(C_i)(\mid C_i \mid \pm 1)}{W_{new}(C_i)^r} - \frac{S(C_i) \mid C_i \mid }{W(C_i)^r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм состоит из следующих этапов:&lt;br /&gt;
&lt;br /&gt;
1. &#039;&#039;&#039;Инициализация&#039;&#039;&#039;. На этом этапе происходит первый проход по таблице с транзакциями для построения начального разбиения, для каждой транзакции определяется кластер исходя из максимизации стоимости.&lt;br /&gt;
&lt;br /&gt;
2. &#039;&#039;&#039;Итерация&#039;&#039;&#039;. На данном этапе для каждой транзакции проводится попытка перемещения в другой кластер для максимизации функции стоимости.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
[[File:InitIter.PNG||500px]]&lt;br /&gt;
&lt;br /&gt;
Первая часть алгоритма - инициализация: для каждой транзакции вычисляется кластер, к которому она будет отнесена исходя из максимизации функции стоимости. Для этого вычисляется вспомогательная функция DeltaAdd, которая считает стоимость добавления транзакции к одному из существующих кластеров, либо к пустому. В итоге транзакция помещается в кластер, для которого цена добавления максимальна.&lt;br /&gt;
&lt;br /&gt;
Вторая часть алгоритма - уточняющие итерации: здесь происходит попытка улучшить вычисленные на первом этапе кластеры. В каждой итерации происходит перебор всех транзакций, и для каждой транзакции вычисляется цена удаления ее из текущего кластера и цена добавления в другой кластер. Суммарная стоимость перемещения будет являться суммой стоимостей удаления и добавления. Если максимальная стоимость перемещения данной транзакции в какой-либо больше нуля, то она перемещается в этот кластер. &lt;br /&gt;
&lt;br /&gt;
Вычисления происходят до тех пор, пока за итерацию происходит хотя бы одно перемещение транзакции. Если за итерацию не было произведено ни одного перемещения, то текущее состояние кластеров является устойчивым и оптимальным. &amp;lt;ref&amp;gt;Павлин Н. Кластеризация категорийных данных: масштабируемый алгоритм CLOPE, https://basegroup.ru/community/articles/clope&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Схема реализации на псевдокоде:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Входные параметры:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - транзакции&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; - коэффициент отталкивания&lt;br /&gt;
&lt;br /&gt;
Выходной параметр:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; кластеры, в начале алгоритма - пустое множество&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация:&#039;&#039;&#039;&lt;br /&gt;
    &#039;&#039;&#039;for&#039;&#039;&#039; t_i in t:&lt;br /&gt;
    max = 0&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; C_j in C:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; DeltaAdd(C_j,t_i,r) &amp;gt; max:&lt;br /&gt;
                max = DeltaAdd(C_j,t_i,r)&lt;br /&gt;
                C_best = C_j&lt;br /&gt;
    &#039;&#039;&#039;put&#039;&#039;&#039; t_i in C_best&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Итерации:&#039;&#039;&#039;&lt;br /&gt;
    move = True&lt;br /&gt;
    &#039;&#039;&#039;while&#039;&#039;&#039; move == True:&lt;br /&gt;
    move = False&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; t_i in t:&lt;br /&gt;
            max = 0&lt;br /&gt;
            C_now = t_i.cluster&lt;br /&gt;
            removeCost = DeltaRemove(C_now,t_i,r)&lt;br /&gt;
            &#039;&#039;&#039;for&#039;&#039;&#039; C_j in C:&lt;br /&gt;
                &#039;&#039;&#039;if&#039;&#039;&#039; DeltaAdd(C_j,t_i,r) + removeCost &amp;gt; max:&lt;br /&gt;
                    max = DeltaAdd(C_j,t_i,r) + removeCost&lt;br /&gt;
                    C_best = C_j&lt;br /&gt;
        if max &amp;gt; 0&lt;br /&gt;
            &#039;&#039;&#039;del&#039;&#039;&#039; t_i from C_now&lt;br /&gt;
            &#039;&#039;&#039;put&#039;&#039;&#039; t_i in C_best&lt;br /&gt;
            move = True&lt;br /&gt;
&lt;br /&gt;
Вспомогательная функция &#039;&#039;&#039;DeltaAdd&#039;&#039;&#039;:&lt;br /&gt;
    &#039;&#039;&#039;function&#039;&#039;&#039; DeltaAdd(C,t,r)&lt;br /&gt;
        S_new=C.size + t.itemCount&lt;br /&gt;
        W_new=C.wigth&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; item in t_i:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; C_j.occ(item) = 0&lt;br /&gt;
                &#039;&#039;W_new = W_new + 1&lt;br /&gt;
        &#039;&#039;&#039;return&#039;&#039;&#039; S_new * (C.count+1) / (W_new ^ r) - (C.size * C.count) / (C.wigth ^ r)&lt;br /&gt;
&lt;br /&gt;
Вспомогательная функция &#039;&#039;&#039;DeltaRemove&#039;&#039;&#039;:&lt;br /&gt;
    &#039;&#039;&#039;function&#039;&#039;&#039; DeltaRemove(C,t,r)&lt;br /&gt;
        S_new=C.size - t.itemCount&lt;br /&gt;
        W_new=C.wigth&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; item in t:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; C_j.occ(item) = 1&lt;br /&gt;
                &#039;&#039;W_new = W_new - 1&lt;br /&gt;
        &#039;&#039;&#039;return&#039;&#039;&#039; S_new * (C.count-1) / (W_new ^ r) - (C.size * C.count) / (C.wigth ^ r)&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
В соответствии с ранее введенным обозначением &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - количество транзакций, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина транзакции(максимальная), &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество кластеров.&lt;br /&gt;
&lt;br /&gt;
Основные вычисления восполняются в функции DeltaAdd/DeltaRemove: производится 1 сложение, не более &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; сложений/вычитаний, 2 умножения, 2 деления, 2 возведения в степень и 1 сложение - итого &amp;lt;math&amp;gt;m + 8&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;k&amp;lt;/math&amp;gt; штук). Итого выполняется &amp;lt;math&amp;gt;n*k*(m+8)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
В добавок к этому при добавлении/удалении транзакции к кластеру производится пересчет его характеристик: &amp;lt;math&amp;gt;m+2&amp;lt;/math&amp;gt; операции.&lt;br /&gt;
&lt;br /&gt;
Из того можно сделать вывод, что оценка сложность алгоритма равна &amp;lt;math&amp;gt;O(n*k*m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
&lt;br /&gt;
На рисунке ниже представлена схема этапа инициализации на примере входной транзакции &#039;&#039;&#039;T&#039;&#039;&#039; и четырех кластеров &#039;&#039;&#039;Cl 1&#039;&#039;&#039;, &#039;&#039;&#039;Cl 2&#039;&#039;&#039;, &#039;&#039;&#039;Cl 3&#039;&#039;&#039; и &#039;&#039;&#039;Cl 4&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Объект &#039;&#039;&#039;DeltaAdd&#039;&#039;&#039; соответствует выполнению соответствующей функции для вычисления цены добавления транзакции на кластер. После выполнения всех &#039;&#039;&#039;DeltaAdd&#039;&#039;&#039; для одной транзакции выполняется определение максимального значения функции и выбор кластера, на который будет помещена транзакция. На этапе инициализации при обработке каждой транзакции количество кластеров может как увеличиться, так и остаться неизменным.&lt;br /&gt;
&lt;br /&gt;
[[File:InitDef.PNG||700px]]&lt;br /&gt;
&lt;br /&gt;
Этап итераций отличается только тем, что на нем дополнительно считается функция &#039;&#039;&#039;DeltaRemove&#039;&#039;&#039; вычисления стоимости удаления транзакции с кластера. На этапе итерации функции DeltaAdd/DeltaRemove могут считать параллельно для каждой транзакции.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Вычисление стоимости добавления/удаления транзакции, которые выполняются функциями DeltaAdd/DeltaRemove, происходит независимо для всех &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; кластеров. Поэтому все вычисления можно производить параллельно. Таким образом сложность алгоритма с &amp;lt;math&amp;gt;O(n*k*m)&amp;lt;/math&amp;gt; понижается до &amp;lt;math&amp;gt;O(n*m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; транзакций длины &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; и коэффициент отталкивания &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
метки классов для каждой транзакции в соответствии с проведенной кластеризацией(числовая последовательность длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной сложности алгоритма определяется количеством кластеров: &amp;lt;math&amp;gt;\dfrac{O(n*k*m)}{O(n*m)} = k&amp;lt;/math&amp;gt;&lt;br /&gt;
* [[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]] алгоритма равна &amp;lt;math&amp;gt;\dfrac{nk(m+8) + m + 2}{nm + n + 1} \cong k&amp;lt;/math&amp;gt;&lt;br /&gt;
* Алгоритм не является [[глоссарий#Устойчивость|&#039;&#039;устойчивым&#039;&#039;]], так как результат работы зависит от порядка чтения транзакций и от текущего набора транзакций в кластере.&lt;br /&gt;
* Выполняется свойство сбалансированности операций между параллельными ветвями алгоритма, так как для каждой транзакции выполняются функции DeltaAdd/DeltaRemove, считающие стоимость добавления/удаления транзакции.&lt;br /&gt;
* Свойство [[глоссарий#Детерминированность|&#039;&#039;детерминированности алгоритмов&#039;&#039;]] не выполняется, так как результат алгоритма зависит от порядка прохождения транзакций. Но если рассматривать транзакции как нумерованный список, то результат будет определен однозначно от запуска к запуску. Однако существует расширение алгоритма, обеспечивающее свойство детерминированности. &amp;lt;ref&amp;gt;Li, Y., Le, J., Wang, M. Improving CLOPE’s Profit Value and Stability with an Optimized Agglomerative Approach. Algorithms 2015, 8, 380-394.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
* Так как алгоритм предназначен для кластеризации категориальных данных, то он практически неприменим для числовой кластеризации.&lt;br /&gt;
* Быстро работает даже для большого количества данных, обеспечивая при этом хорошее качество кластеризации&lt;br /&gt;
* Имеет простую реализацию&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
Проверка масштабируемости проводилась на суперкомпьютере &amp;quot;Ломоносов&amp;quot; с числом процессоров 1, 8, 16, 32 и 64 на десяти различных сетках - от 1000×1000 до 10000×10000. Результаты проверки на графике ниже.&lt;br /&gt;
&lt;br /&gt;
[[file:Graf_lom.png||700px]]&lt;br /&gt;
&lt;br /&gt;
Таким образом, можно сделать вывод о том, что алгоритм кластеризации CLOPE является масштабируемым.&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
* http://weka.sourceforge.net/doc.stable/weka/clusterers/CLOPE.html - реализация в open source библиотеке для анализа данных WEKA(Waikato Environment for Knowledge Analysis) на языке Java&lt;br /&gt;
Также существуют пользовательские реализации алгоритма:&lt;br /&gt;
* https://github.com/infozor/php_mysql_clustering_clope - реализация алгоритма на PHP&lt;br /&gt;
* https://github.com/Tolsi/scala-clope - реализация алгоритма Scala&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:%D0%9F%D0%B0%D0%B2%D0%B5%D0%BB/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BA%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D0%B9%D0%BD%D1%8B%D1%85_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85_CLOPE&amp;diff=21601</id>
		<title>Участник:Павел/Алгоритм кластеризации категорийных данных CLOPE</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9F%D0%B0%D0%B2%D0%B5%D0%BB/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BA%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D0%B9%D0%BD%D1%8B%D1%85_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85_CLOPE&amp;diff=21601"/>
		<updated>2017-01-19T14:35: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;
Алгоритм CLOPE (Clustering with sLOPE&amp;lt;ref&amp;gt;Yang, Y., Guan, H., You. J. CLOPE: A fast and Effective Clustering Algorithm for Transactional Data In Proc. of SIGKDD’02, July 23-26, 2002, Edmonton, Alberta, Canada.&amp;lt;/ref&amp;gt;) неирархический метод кластеризации, предназначенный для кластеризации огромных наборов категорийных данных. К достоинствам алгоритма относятся высокие масштабируемость и скорость работы и качество кластеризации, что достигается использованием глобального критерия оптимизации на основе максимизации градиента высоты гистограммы кластера. Отличается простотой программной реализации. &lt;br /&gt;
&lt;br /&gt;
Во время работы алгоритм хранит в памяти небольшое количество информации по каждому кластеру и требует минимальное число сканирований набора данных. CLOPE автоматически подбирает количество кластеров, причем это регулируется одним единственным параметром - коэффициентом отталкивания &amp;lt;math&amp;gt; r &amp;lt;/math&amp;gt;. При этом он обеспечивает более высокую производительность и лучшее качество кластеризации в сравнении с многими иерархическими алгоритмами.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
Пусть имеется база транзакций &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, состоящая из множества транзакций &amp;lt;math&amp;gt;\{t_1,t_2,...,t_n\}&amp;lt;/math&amp;gt;. Каждая транзакция есть набор объектов &amp;lt;math&amp;gt;\{i_1,...,i_m\}&amp;lt;/math&amp;gt;. Множество кластеров &amp;lt;math&amp;gt;\{C_1,...,C_k\}&amp;lt;/math&amp;gt; есть разбиение множества &amp;lt;math&amp;gt;\{t_1,...,t_n\}&amp;lt;/math&amp;gt;, такое, что &amp;lt;math&amp;gt;C_1 \cup \dots \cup C_k=\{t_1,...,t_n\}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_i \ne \empty&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_i \cap C_j = \empty &amp;lt;/math&amp;gt;, для &amp;lt;math&amp;gt;i \ge 1, k \ge j&amp;lt;/math&amp;gt;. Каждый элемент &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; называется кластером, а &amp;lt;math&amp;gt;n, m, k&amp;lt;/math&amp;gt; – количество транзакций, количество объектов в базе транзакций и число кластеров соответственно.&lt;br /&gt;
&lt;br /&gt;
Каждый кластер &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; имеет следующие характеристики:&lt;br /&gt;
&amp;lt;math&amp;gt;D(C)&amp;lt;/math&amp;gt; – множество уникальных объектов;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;Occ(i,C)&amp;lt;/math&amp;gt; – количество вхождений (частота) объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; в кластер &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;S(C)= \sum_{i \in D(C)} Occ(i,C)= \sum_{t_i \in C}  \mid t_i  \mid , &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;W(C)=  \mid D(C) \mid ,H(C)=S(C)/W(C) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Функция стоимости:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; Profit(C) = \frac{\sum^{k}_{i=1} G(C_i) \times \mid C_i \mid} {\sum^{k}_{i=1} \mid C_i \mid } = \frac{\sum^{k}_{i=1} \frac{S(C_i)}{W(C_i)^r} \times \mid C_i \mid} {\sum^{k}_{i=1} \mid C_i \mid }  &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;\mid C_i \mid&amp;lt;/math&amp;gt;  количество объектов в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом кластере, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; – количество кластеров, &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; – коэффициент отталкивания &amp;lt;math&amp;gt;(0 &amp;lt; r \le 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С помощью параметра &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; регулируется уровень сходства транзакций внутри кластера, и, как&lt;br /&gt;
следствие, финальное количество кластеров. Этот коэффициент подбирается пользователем. Чем больше &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt;, тем ниже уровень сходства и тем больше кластеров будет сгенерировано.&lt;br /&gt;
&lt;br /&gt;
Постановка задачи кластеризации алгоритмом CLOPE выглядит следующим образом: &lt;br /&gt;
&lt;br /&gt;
для заданных &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; найти разбиение &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; такое, что: &lt;br /&gt;
&amp;lt;math&amp;gt;Profit(C) \longrightarrow max &amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит в вычислении на каждой итерации стоимости добавления и удаления транзакции из кластера: &lt;br /&gt;
&lt;br /&gt;
*вычисление нового размера кластера &amp;lt;math&amp;gt;S_{new}(C_i)=S(C_i) \pm \mid(t_n)\mid &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\mid(t_n)\mid&amp;lt;/math&amp;gt; - длина транзакции&lt;br /&gt;
&lt;br /&gt;
*вычисление новой ширины кластера &amp;lt;math&amp;gt;W_{new}(C_i)=\mid D(C_i \cup t_n)|&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*вычисление стоимости &amp;lt;math&amp;gt;\frac{S_{new}(C_i)(\mid C_i \mid \pm 1)}{W_{new}(C_i)^r} - \frac{S(C_i) \mid C_i \mid }{W(C_i)^r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм состоит из следующих этапов:&lt;br /&gt;
&lt;br /&gt;
1. &#039;&#039;&#039;Инициализация&#039;&#039;&#039;. На этом этапе происходит первый проход по таблице с транзакциями для построения начального разбиения, для каждой транзакции определяется кластер исходя из максимизации стоимости.&lt;br /&gt;
&lt;br /&gt;
2. &#039;&#039;&#039;Итерация&#039;&#039;&#039;. На данном этапе для каждой транзакции проводится попытка перемещения в другой кластер для максимизации функции стоимости.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
[[File:InitIter.PNG||500px]]&lt;br /&gt;
&lt;br /&gt;
Первая часть алгоритма - инициализация: для каждой транзакции вычисляется кластер, к которому она будет отнесена исходя из максимизации функции стоимости. Для этого вычисляется вспомогательная функция DeltaAdd, которая считает стоимость добавления транзакции к одному из существующих кластеров, либо к пустому. В итоге транзакция помещается в кластер, для которого цена добавления максимальна.&lt;br /&gt;
&lt;br /&gt;
Вторая часть алгоритма - уточняющие итерации: здесь происходит попытка улучшить вычисленные на первом этапе кластеры. В каждой итерации происходит перебор всех транзакций, и для каждой транзакции вычисляется цена удаления ее из текущего кластера и цена добавления в другой кластер. Суммарная стоимость перемещения будет являться суммой стоимостей удаления и добавления. Если максимальная стоимость перемещения данной транзакции в какой-либо больше нуля, то она перемещается в этот кластер. &lt;br /&gt;
&lt;br /&gt;
Вычисления происходят до тех пор, пока за итерацию происходит хотя бы одно перемещение транзакции. Если за итерацию не было произведено ни одного перемещения, то текущее состояние кластеров является устойчивым и оптимальным. &amp;lt;ref&amp;gt;Павлин Н. Кластеризация категорийных данных: масштабируемый алгоритм CLOPE, https://basegroup.ru/community/articles/clope&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Схема реализации на псевдокоде:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Входные параметры:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - транзакции&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; - коэффициент отталкивания&lt;br /&gt;
&lt;br /&gt;
Выходной параметр:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; кластеры, в начале алгоритма - пустое множество&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация:&#039;&#039;&#039;&lt;br /&gt;
    &#039;&#039;&#039;for&#039;&#039;&#039; t_i in t:&lt;br /&gt;
    max = 0&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; C_j in C:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; DeltaAdd(C_j,t_i,r) &amp;gt; max:&lt;br /&gt;
                max = DeltaAdd(C_j,t_i,r)&lt;br /&gt;
                C_best = C_j&lt;br /&gt;
    &#039;&#039;&#039;put&#039;&#039;&#039; t_i in C_best&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Итерации:&#039;&#039;&#039;&lt;br /&gt;
    move = True&lt;br /&gt;
    &#039;&#039;&#039;while&#039;&#039;&#039; move == True:&lt;br /&gt;
    move = False&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; t_i in t:&lt;br /&gt;
            max = 0&lt;br /&gt;
            C_now = t_i.cluster&lt;br /&gt;
            removeCost = DeltaRemove(C_now,t_i,r)&lt;br /&gt;
            &#039;&#039;&#039;for&#039;&#039;&#039; C_j in C:&lt;br /&gt;
                &#039;&#039;&#039;if&#039;&#039;&#039; DeltaAdd(C_j,t_i,r) + removeCost &amp;gt; max:&lt;br /&gt;
                    max = DeltaAdd(C_j,t_i,r) + removeCost&lt;br /&gt;
                    C_best = C_j&lt;br /&gt;
        if max &amp;gt; 0&lt;br /&gt;
            &#039;&#039;&#039;del&#039;&#039;&#039; t_i from C_now&lt;br /&gt;
            &#039;&#039;&#039;put&#039;&#039;&#039; t_i in C_best&lt;br /&gt;
            move = True&lt;br /&gt;
&lt;br /&gt;
Вспомогательная функция &#039;&#039;&#039;DeltaAdd&#039;&#039;&#039;:&lt;br /&gt;
    &#039;&#039;&#039;function&#039;&#039;&#039; DeltaAdd(C,t,r)&lt;br /&gt;
        S_new=C.size + t.itemCount&lt;br /&gt;
        W_new=C.wigth&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; item in t_i:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; C_j.occ(item) = 0&lt;br /&gt;
                &#039;&#039;W_new = W_new + 1&lt;br /&gt;
        &#039;&#039;&#039;return&#039;&#039;&#039; S_new * (C.count+1) / (W_new ^ r) - (C.size * C.count) / (C.wigth ^ r)&lt;br /&gt;
&lt;br /&gt;
Вспомогательная функция &#039;&#039;&#039;DeltaRemove&#039;&#039;&#039;:&lt;br /&gt;
    &#039;&#039;&#039;function&#039;&#039;&#039; DeltaRemove(C,t,r)&lt;br /&gt;
        S_new=C.size - t.itemCount&lt;br /&gt;
        W_new=C.wigth&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; item in t:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; C_j.occ(item) = 1&lt;br /&gt;
                &#039;&#039;W_new = W_new - 1&lt;br /&gt;
        &#039;&#039;&#039;return&#039;&#039;&#039; S_new * (C.count-1) / (W_new ^ r) - (C.size * C.count) / (C.wigth ^ r)&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
В соответствии с ранее введенным обозначением &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - количество транзакций, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина транзакции(максимальная), &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество кластеров.&lt;br /&gt;
&lt;br /&gt;
Основные вычисления восполняются в функции DeltaAdd/DeltaRemove: производится 1 сложение, не более &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; сложений/вычитаний, 2 умножения, 2 деления, 2 возведения в степень и 1 сложение - итого &amp;lt;math&amp;gt;m + 8&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;k&amp;lt;/math&amp;gt; штук). Итого выполняется &amp;lt;math&amp;gt;n*k*(m+8)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
В добавок к этому при добавлении/удалении транзакции к кластеру производится пересчет его характеристик: &amp;lt;math&amp;gt;m+2&amp;lt;/math&amp;gt; операции.&lt;br /&gt;
&lt;br /&gt;
Из того можно сделать вывод, что оценка сложность алгоритма равна &amp;lt;math&amp;gt;O(n*k*m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
&lt;br /&gt;
На рисунке ниже представлена схема этапа инициализации на примере входной транзакции &#039;&#039;&#039;T&#039;&#039;&#039; и четырех кластеров &#039;&#039;&#039;Cl 1&#039;&#039;&#039;, &#039;&#039;&#039;Cl 2&#039;&#039;&#039;, &#039;&#039;&#039;Cl 3&#039;&#039;&#039; и &#039;&#039;&#039;Cl 4&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Объект &#039;&#039;&#039;DeltaAdd&#039;&#039;&#039; соответствует выполнению соответствующей функции для вычисления цены добавления транзакции на кластер. После выполнения всех &#039;&#039;&#039;DeltaAdd&#039;&#039;&#039; для одной транзакции выполняется определение максимального значения функции и выбор кластера, на который будет помещена транзакция. На этапе инициализации при обработке каждой транзакции количество кластеров может как увеличиться, так и остаться неизменным.&lt;br /&gt;
&lt;br /&gt;
[[File:InitDef.PNG||700px]]&lt;br /&gt;
&lt;br /&gt;
Этап итераций отличается только тем, что на нем дополнительно считается функция &#039;&#039;&#039;DeltaRemove&#039;&#039;&#039; вычисления стоимости удаления транзакции с кластера. На этапе итерации функции DeltaAdd/DeltaRemove могут считать параллельно для каждой транзакции.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Вычисление стоимости добавления/удаления транзакции, которые выполняются функциями DeltaAdd/DeltaRemove, происходит независимо для всех &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; кластеров. Поэтому все вычисления можно производить параллельно. Таким образом сложность алгоритма с &amp;lt;math&amp;gt;O(n*k*m)&amp;lt;/math&amp;gt; понижается до &amp;lt;math&amp;gt;O(n*m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; транзакций длины &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; и коэффициент отталкивания &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
метки классов для каждой транзакции в соответствии с проведенной кластеризацией(числовая последовательность длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной сложности алгоритма определяется количеством кластеров: &amp;lt;math&amp;gt;\dfrac{O(n*k*m)}{O(n*m)} = k&amp;lt;/math&amp;gt;&lt;br /&gt;
* [[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]] алгоритма равна &amp;lt;math&amp;gt;\dfrac{nk(m+8) + m + 2}{nm + n + 1} \cong k&amp;lt;/math&amp;gt;&lt;br /&gt;
* Алгоритм не является [[глоссарий#Устойчивость|&#039;&#039;устойчивым&#039;&#039;]], так как результат работы зависит от порядка чтения транзакций и от текущего набора транзакций в кластере.&lt;br /&gt;
* Выполняется свойство сбалансированности операций между параллельными ветвями алгоритма, так как для каждой транзакции выполняются функции DeltaAdd/DeltaRemove, считающие стоимость добавления/удаления транзакции.&lt;br /&gt;
* Свойство [[глоссарий#Детерминированность|&#039;&#039;детерминированности алгоритмов&#039;&#039;]] не выполняется, так как результат алгоритма зависит от порядка прохождения транзакций. Но если рассматривать транзакции как нумерованный список, то результат будет определен однозначно от запуска к запуску. Однако существует расширение алгоритма, обеспечивающее свойство детерминированности. &amp;lt;ref&amp;gt;Li, Y., Le, J., Wang, M. Improving CLOPE’s Profit Value and Stability with an Optimized Agglomerative Approach. Algorithms 2015, 8, 380-394.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
* Так как алгоритм предназначен для кластеризации категориальных данных, то он практически неприменим для числовой кластеризации.&lt;br /&gt;
* Быстро работает даже для большого количества данных, обеспечивая при этом хорошее качество кластеризации&lt;br /&gt;
* Имеет простую реализацию&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
Проверка масштабируемости проводилась на суперкомпьютере &amp;quot;Ломоносов&amp;quot; с числом процессоров 1, 8, 16, 32 и 64 на десяти различных сетках - от 1000×1000 до 10000×10000. Результаты проверки на графике ниже.&lt;br /&gt;
[[file:Graf_lom.png||700px]]&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
* http://weka.sourceforge.net/doc.stable/weka/clusterers/CLOPE.html - реализация в open source библиотеке для анализа данных WEKA(Waikato Environment for Knowledge Analysis) на языке Java&lt;br /&gt;
Также существуют пользовательские реализации алгоритма:&lt;br /&gt;
* https://github.com/infozor/php_mysql_clustering_clope - реализация алгоритма на PHP&lt;br /&gt;
* https://github.com/Tolsi/scala-clope - реализация алгоритма Scala&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:%D0%9F%D0%B0%D0%B2%D0%B5%D0%BB/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BA%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D0%B9%D0%BD%D1%8B%D1%85_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85_CLOPE&amp;diff=21600</id>
		<title>Участник:Павел/Алгоритм кластеризации категорийных данных CLOPE</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9F%D0%B0%D0%B2%D0%B5%D0%BB/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BA%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D0%B9%D0%BD%D1%8B%D1%85_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85_CLOPE&amp;diff=21600"/>
		<updated>2017-01-19T14:26:07Z</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;
Алгоритм CLOPE (Clustering with sLOPE&amp;lt;ref&amp;gt;Yang, Y., Guan, H., You. J. CLOPE: A fast and Effective Clustering Algorithm for Transactional Data In Proc. of SIGKDD’02, July 23-26, 2002, Edmonton, Alberta, Canada.&amp;lt;/ref&amp;gt;) неирархический метод кластеризации, предназначенный для кластеризации огромных наборов категорийных данных. К достоинствам алгоритма относятся высокие масштабируемость и скорость работы и качество кластеризации, что достигается использованием глобального критерия оптимизации на основе максимизации градиента высоты гистограммы кластера. Отличается простотой программной реализации. &lt;br /&gt;
&lt;br /&gt;
Во время работы алгоритм хранит в памяти небольшое количество информации по каждому кластеру и требует минимальное число сканирований набора данных. CLOPE автоматически подбирает количество кластеров, причем это регулируется одним единственным параметром - коэффициентом отталкивания &amp;lt;math&amp;gt; r &amp;lt;/math&amp;gt;. При этом он обеспечивает более высокую производительность и лучшее качество кластеризации в сравнении с многими иерархическими алгоритмами.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
Пусть имеется база транзакций &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, состоящая из множества транзакций &amp;lt;math&amp;gt;\{t_1,t_2,...,t_n\}&amp;lt;/math&amp;gt;. Каждая транзакция есть набор объектов &amp;lt;math&amp;gt;\{i_1,...,i_m\}&amp;lt;/math&amp;gt;. Множество кластеров &amp;lt;math&amp;gt;\{C_1,...,C_k\}&amp;lt;/math&amp;gt; есть разбиение множества &amp;lt;math&amp;gt;\{t_1,...,t_n\}&amp;lt;/math&amp;gt;, такое, что &amp;lt;math&amp;gt;C_1 \cup \dots \cup C_k=\{t_1,...,t_n\}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_i \ne \empty&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_i \cap C_j = \empty &amp;lt;/math&amp;gt;, для &amp;lt;math&amp;gt;i \ge 1, k \ge j&amp;lt;/math&amp;gt;. Каждый элемент &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; называется кластером, а &amp;lt;math&amp;gt;n, m, k&amp;lt;/math&amp;gt; – количество транзакций, количество объектов в базе транзакций и число кластеров соответственно.&lt;br /&gt;
&lt;br /&gt;
Каждый кластер &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; имеет следующие характеристики:&lt;br /&gt;
&amp;lt;math&amp;gt;D(C)&amp;lt;/math&amp;gt; – множество уникальных объектов;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;Occ(i,C)&amp;lt;/math&amp;gt; – количество вхождений (частота) объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; в кластер &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;S(C)= \sum_{i \in D(C)} Occ(i,C)= \sum_{t_i \in C}  \mid t_i  \mid , &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;W(C)=  \mid D(C) \mid ,H(C)=S(C)/W(C) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Функция стоимости:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; Profit(C) = \frac{\sum^{k}_{i=1} G(C_i) \times \mid C_i \mid} {\sum^{k}_{i=1} \mid C_i \mid } = \frac{\sum^{k}_{i=1} \frac{S(C_i)}{W(C_i)^r} \times \mid C_i \mid} {\sum^{k}_{i=1} \mid C_i \mid }  &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;\mid C_i \mid&amp;lt;/math&amp;gt;  количество объектов в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом кластере, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; – количество кластеров, &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; – коэффициент отталкивания &amp;lt;math&amp;gt;(0 &amp;lt; r \le 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С помощью параметра &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; регулируется уровень сходства транзакций внутри кластера, и, как&lt;br /&gt;
следствие, финальное количество кластеров. Этот коэффициент подбирается пользователем. Чем больше &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt;, тем ниже уровень сходства и тем больше кластеров будет сгенерировано.&lt;br /&gt;
&lt;br /&gt;
Постановка задачи кластеризации алгоритмом CLOPE выглядит следующим образом: &lt;br /&gt;
&lt;br /&gt;
для заданных &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; найти разбиение &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; такое, что: &lt;br /&gt;
&amp;lt;math&amp;gt;Profit(C) \longrightarrow max &amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит в вычислении на каждой итерации стоимости добавления и удаления транзакции из кластера: &lt;br /&gt;
&lt;br /&gt;
*вычисление нового размера кластера &amp;lt;math&amp;gt;S_{new}(C_i)=S(C_i) \pm \mid(t_n)\mid &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\mid(t_n)\mid&amp;lt;/math&amp;gt; - длина транзакции&lt;br /&gt;
&lt;br /&gt;
*вычисление новой ширины кластера &amp;lt;math&amp;gt;W_{new}(C_i)=\mid D(C_i \cup t_n)|&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*вычисление стоимости &amp;lt;math&amp;gt;\frac{S_{new}(C_i)(\mid C_i \mid \pm 1)}{W_{new}(C_i)^r} - \frac{S(C_i) \mid C_i \mid }{W(C_i)^r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм состоит из следующих этапов:&lt;br /&gt;
&lt;br /&gt;
1. &#039;&#039;&#039;Инициализация&#039;&#039;&#039;. На этом этапе происходит первый проход по таблице с транзакциями для построения начального разбиения, для каждой транзакции определяется кластер исходя из максимизации стоимости.&lt;br /&gt;
&lt;br /&gt;
2. &#039;&#039;&#039;Итерация&#039;&#039;&#039;. На данном этапе для каждой транзакции проводится попытка перемещения в другой кластер для максимизации функции стоимости.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
[[File:InitIter.PNG||500px]]&lt;br /&gt;
&lt;br /&gt;
Первая часть алгоритма - инициализация: для каждой транзакции вычисляется кластер, к которому она будет отнесена исходя из максимизации функции стоимости. Для этого вычисляется вспомогательная функция DeltaAdd, которая считает стоимость добавления транзакции к одному из существующих кластеров, либо к пустому. В итоге транзакция помещается в кластер, для которого цена добавления максимальна.&lt;br /&gt;
&lt;br /&gt;
Вторая часть алгоритма - уточняющие итерации: здесь происходит попытка улучшить вычисленные на первом этапе кластеры. В каждой итерации происходит перебор всех транзакций, и для каждой транзакции вычисляется цена удаления ее из текущего кластера и цена добавления в другой кластер. Суммарная стоимость перемещения будет являться суммой стоимостей удаления и добавления. Если максимальная стоимость перемещения данной транзакции в какой-либо больше нуля, то она перемещается в этот кластер. &lt;br /&gt;
&lt;br /&gt;
Вычисления происходят до тех пор, пока за итерацию происходит хотя бы одно перемещение транзакции. Если за итерацию не было произведено ни одного перемещения, то текущее состояние кластеров является устойчивым и оптимальным. &amp;lt;ref&amp;gt;Павлин Н. Кластеризация категорийных данных: масштабируемый алгоритм CLOPE, https://basegroup.ru/community/articles/clope&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Схема реализации на псевдокоде:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Входные параметры:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - транзакции&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; - коэффициент отталкивания&lt;br /&gt;
&lt;br /&gt;
Выходной параметр:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; кластеры, в начале алгоритма - пустое множество&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация:&#039;&#039;&#039;&lt;br /&gt;
    &#039;&#039;&#039;for&#039;&#039;&#039; t_i in t:&lt;br /&gt;
    max = 0&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; C_j in C:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; DeltaAdd(C_j,t_i,r) &amp;gt; max:&lt;br /&gt;
                max = DeltaAdd(C_j,t_i,r)&lt;br /&gt;
                C_best = C_j&lt;br /&gt;
    &#039;&#039;&#039;put&#039;&#039;&#039; t_i in C_best&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Итерации:&#039;&#039;&#039;&lt;br /&gt;
    move = True&lt;br /&gt;
    &#039;&#039;&#039;while&#039;&#039;&#039; move == True:&lt;br /&gt;
    move = False&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; t_i in t:&lt;br /&gt;
            max = 0&lt;br /&gt;
            C_now = t_i.cluster&lt;br /&gt;
            removeCost = DeltaRemove(C_now,t_i,r)&lt;br /&gt;
            &#039;&#039;&#039;for&#039;&#039;&#039; C_j in C:&lt;br /&gt;
                &#039;&#039;&#039;if&#039;&#039;&#039; DeltaAdd(C_j,t_i,r) + removeCost &amp;gt; max:&lt;br /&gt;
                    max = DeltaAdd(C_j,t_i,r) + removeCost&lt;br /&gt;
                    C_best = C_j&lt;br /&gt;
        if max &amp;gt; 0&lt;br /&gt;
            &#039;&#039;&#039;del&#039;&#039;&#039; t_i from C_now&lt;br /&gt;
            &#039;&#039;&#039;put&#039;&#039;&#039; t_i in C_best&lt;br /&gt;
            move = True&lt;br /&gt;
&lt;br /&gt;
Вспомогательная функция &#039;&#039;&#039;DeltaAdd&#039;&#039;&#039;:&lt;br /&gt;
    &#039;&#039;&#039;function&#039;&#039;&#039; DeltaAdd(C,t,r)&lt;br /&gt;
        S_new=C.size + t.itemCount&lt;br /&gt;
        W_new=C.wigth&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; item in t_i:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; C_j.occ(item) = 0&lt;br /&gt;
                &#039;&#039;W_new = W_new + 1&lt;br /&gt;
        &#039;&#039;&#039;return&#039;&#039;&#039; S_new * (C.count+1) / (W_new ^ r) - (C.size * C.count) / (C.wigth ^ r)&lt;br /&gt;
&lt;br /&gt;
Вспомогательная функция &#039;&#039;&#039;DeltaRemove&#039;&#039;&#039;:&lt;br /&gt;
    &#039;&#039;&#039;function&#039;&#039;&#039; DeltaRemove(C,t,r)&lt;br /&gt;
        S_new=C.size - t.itemCount&lt;br /&gt;
        W_new=C.wigth&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; item in t:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; C_j.occ(item) = 1&lt;br /&gt;
                &#039;&#039;W_new = W_new - 1&lt;br /&gt;
        &#039;&#039;&#039;return&#039;&#039;&#039; S_new * (C.count-1) / (W_new ^ r) - (C.size * C.count) / (C.wigth ^ r)&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
В соответствии с ранее введенным обозначением &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - количество транзакций, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина транзакции(максимальная), &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество кластеров.&lt;br /&gt;
&lt;br /&gt;
Основные вычисления восполняются в функции DeltaAdd/DeltaRemove: производится 1 сложение, не более &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; сложений/вычитаний, 2 умножения, 2 деления, 2 возведения в степень и 1 сложение - итого &amp;lt;math&amp;gt;m + 8&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;k&amp;lt;/math&amp;gt; штук). Итого выполняется &amp;lt;math&amp;gt;n*k*(m+8)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
В добавок к этому при добавлении/удалении транзакции к кластеру производится пересчет его характеристик: &amp;lt;math&amp;gt;m+2&amp;lt;/math&amp;gt; операции.&lt;br /&gt;
&lt;br /&gt;
Из того можно сделать вывод, что оценка сложность алгоритма равна &amp;lt;math&amp;gt;O(n*k*m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
&lt;br /&gt;
На рисунке ниже представлена схема этапа инициализации на примере входной транзакции &#039;&#039;&#039;T&#039;&#039;&#039; и четырех кластеров &#039;&#039;&#039;Cl 1&#039;&#039;&#039;, &#039;&#039;&#039;Cl 2&#039;&#039;&#039;, &#039;&#039;&#039;Cl 3&#039;&#039;&#039; и &#039;&#039;&#039;Cl 4&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Объект &#039;&#039;&#039;DeltaAdd&#039;&#039;&#039; соответствует выполнению соответствующей функции для вычисления цены добавления транзакции на кластер. После выполнения всех &#039;&#039;&#039;DeltaAdd&#039;&#039;&#039; для одной транзакции выполняется определение максимального значения функции и выбор кластера, на который будет помещена транзакция. На этапе инициализации при обработке каждой транзакции количество кластеров может как увеличиться, так и остаться неизменным.&lt;br /&gt;
&lt;br /&gt;
[[File:InitDef.PNG||700px]]&lt;br /&gt;
&lt;br /&gt;
Этап итераций отличается только тем, что на нем дополнительно считается функция &#039;&#039;&#039;DeltaRemove&#039;&#039;&#039; вычисления стоимости удаления транзакции с кластера. На этапе итерации функции DeltaAdd/DeltaRemove могут считать параллельно для каждой транзакции.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Вычисление стоимости добавления/удаления транзакции, которые выполняются функциями DeltaAdd/DeltaRemove, происходит независимо для всех &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; кластеров. Поэтому все вычисления можно производить параллельно. Таким образом сложность алгоритма с &amp;lt;math&amp;gt;O(n*k*m)&amp;lt;/math&amp;gt; понижается до &amp;lt;math&amp;gt;O(n*m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; транзакций длины &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; и коэффициент отталкивания &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
метки классов для каждой транзакции в соответствии с проведенной кластеризацией(числовая последовательность длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной сложности алгоритма определяется количеством кластеров: &amp;lt;math&amp;gt;\dfrac{O(n*k*m)}{O(n*m)} = k&amp;lt;/math&amp;gt;&lt;br /&gt;
* [[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]] алгоритма равна &amp;lt;math&amp;gt;\dfrac{nk(m+8) + m + 2}{nm + n + 1} \cong k&amp;lt;/math&amp;gt;&lt;br /&gt;
* Алгоритм не является [[глоссарий#Устойчивость|&#039;&#039;устойчивым&#039;&#039;]], так как результат работы зависит от порядка чтения транзакций и от текущего набора транзакций в кластере.&lt;br /&gt;
* Выполняется свойство сбалансированности операций между параллельными ветвями алгоритма, так как для каждой транзакции выполняются функции DeltaAdd/DeltaRemove, считающие стоимость добавления/удаления транзакции.&lt;br /&gt;
* Свойство [[глоссарий#Детерминированность|&#039;&#039;детерминированности алгоритмов&#039;&#039;]] не выполняется, так как результат алгоритма зависит от порядка прохождения транзакций. Но если рассматривать транзакции как нумерованный список, то результат будет определен однозначно от запуска к запуску. Однако существует расширение алгоритма, обеспечивающее свойство детерминированности. &amp;lt;ref&amp;gt;Li, Y., Le, J., Wang, M. Improving CLOPE’s Profit Value and Stability with an Optimized Agglomerative Approach. Algorithms 2015, 8, 380-394.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
* Так как алгоритм предназначен для кластеризации категориальных данных, то он практически неприменим для числовой кластеризации.&lt;br /&gt;
* Быстро работает даже для большого количества данных, обеспечивая при этом хорошее качество кластеризации&lt;br /&gt;
* Имеет простую реализацию&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
Проверка масштабируемости проводилась на суперкомпьютере &amp;quot;Ломоносов&amp;quot; с числом процессоров 1, 8, 16, 32 и 64. Результаты проверки на графике ниже.&lt;br /&gt;
[[file:Graf_lom.png||700px]]&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
* http://weka.sourceforge.net/doc.stable/weka/clusterers/CLOPE.html - реализация в open source библиотеке для анализа данных WEKA(Waikato Environment for Knowledge Analysis) на языке Java&lt;br /&gt;
Также существуют пользовательские реализации алгоритма:&lt;br /&gt;
* https://github.com/infozor/php_mysql_clustering_clope - реализация алгоритма на PHP&lt;br /&gt;
* https://github.com/Tolsi/scala-clope - реализация алгоритма Scala&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:%D0%9F%D0%B0%D0%B2%D0%B5%D0%BB/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BA%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D0%B9%D0%BD%D1%8B%D1%85_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85_CLOPE&amp;diff=21599</id>
		<title>Участник:Павел/Алгоритм кластеризации категорийных данных CLOPE</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9F%D0%B0%D0%B2%D0%B5%D0%BB/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BA%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D0%B9%D0%BD%D1%8B%D1%85_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85_CLOPE&amp;diff=21599"/>
		<updated>2017-01-19T14:25:31Z</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;
Алгоритм CLOPE (Clustering with sLOPE&amp;lt;ref&amp;gt;Yang, Y., Guan, H., You. J. CLOPE: A fast and Effective Clustering Algorithm for Transactional Data In Proc. of SIGKDD’02, July 23-26, 2002, Edmonton, Alberta, Canada.&amp;lt;/ref&amp;gt;) неирархический метод кластеризации, предназначенный для кластеризации огромных наборов категорийных данных. К достоинствам алгоритма относятся высокие масштабируемость и скорость работы и качество кластеризации, что достигается использованием глобального критерия оптимизации на основе максимизации градиента высоты гистограммы кластера. Отличается простотой программной реализации. &lt;br /&gt;
&lt;br /&gt;
Во время работы алгоритм хранит в памяти небольшое количество информации по каждому кластеру и требует минимальное число сканирований набора данных. CLOPE автоматически подбирает количество кластеров, причем это регулируется одним единственным параметром - коэффициентом отталкивания &amp;lt;math&amp;gt; r &amp;lt;/math&amp;gt;. При этом он обеспечивает более высокую производительность и лучшее качество кластеризации в сравнении с многими иерархическими алгоритмами.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
Пусть имеется база транзакций &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, состоящая из множества транзакций &amp;lt;math&amp;gt;\{t_1,t_2,...,t_n\}&amp;lt;/math&amp;gt;. Каждая транзакция есть набор объектов &amp;lt;math&amp;gt;\{i_1,...,i_m\}&amp;lt;/math&amp;gt;. Множество кластеров &amp;lt;math&amp;gt;\{C_1,...,C_k\}&amp;lt;/math&amp;gt; есть разбиение множества &amp;lt;math&amp;gt;\{t_1,...,t_n\}&amp;lt;/math&amp;gt;, такое, что &amp;lt;math&amp;gt;C_1 \cup \dots \cup C_k=\{t_1,...,t_n\}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_i \ne \empty&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_i \cap C_j = \empty &amp;lt;/math&amp;gt;, для &amp;lt;math&amp;gt;i \ge 1, k \ge j&amp;lt;/math&amp;gt;. Каждый элемент &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; называется кластером, а &amp;lt;math&amp;gt;n, m, k&amp;lt;/math&amp;gt; – количество транзакций, количество объектов в базе транзакций и число кластеров соответственно.&lt;br /&gt;
&lt;br /&gt;
Каждый кластер &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; имеет следующие характеристики:&lt;br /&gt;
&amp;lt;math&amp;gt;D(C)&amp;lt;/math&amp;gt; – множество уникальных объектов;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;Occ(i,C)&amp;lt;/math&amp;gt; – количество вхождений (частота) объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; в кластер &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;S(C)= \sum_{i \in D(C)} Occ(i,C)= \sum_{t_i \in C}  \mid t_i  \mid , &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;W(C)=  \mid D(C) \mid ,H(C)=S(C)/W(C) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Функция стоимости:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; Profit(C) = \frac{\sum^{k}_{i=1} G(C_i) \times \mid C_i \mid} {\sum^{k}_{i=1} \mid C_i \mid } = \frac{\sum^{k}_{i=1} \frac{S(C_i)}{W(C_i)^r} \times \mid C_i \mid} {\sum^{k}_{i=1} \mid C_i \mid }  &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;\mid C_i \mid&amp;lt;/math&amp;gt;  количество объектов в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом кластере, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; – количество кластеров, &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; – коэффициент отталкивания &amp;lt;math&amp;gt;(0 &amp;lt; r \le 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С помощью параметра &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; регулируется уровень сходства транзакций внутри кластера, и, как&lt;br /&gt;
следствие, финальное количество кластеров. Этот коэффициент подбирается пользователем. Чем больше &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt;, тем ниже уровень сходства и тем больше кластеров будет сгенерировано.&lt;br /&gt;
&lt;br /&gt;
Постановка задачи кластеризации алгоритмом CLOPE выглядит следующим образом: &lt;br /&gt;
&lt;br /&gt;
для заданных &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; найти разбиение &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; такое, что: &lt;br /&gt;
&amp;lt;math&amp;gt;Profit(C) \longrightarrow max &amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит в вычислении на каждой итерации стоимости добавления и удаления транзакции из кластера: &lt;br /&gt;
&lt;br /&gt;
*вычисление нового размера кластера &amp;lt;math&amp;gt;S_{new}(C_i)=S(C_i) \pm \mid(t_n)\mid &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\mid(t_n)\mid&amp;lt;/math&amp;gt; - длина транзакции&lt;br /&gt;
&lt;br /&gt;
*вычисление новой ширины кластера &amp;lt;math&amp;gt;W_{new}(C_i)=\mid D(C_i \cup t_n)|&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*вычисление стоимости &amp;lt;math&amp;gt;\frac{S_{new}(C_i)(\mid C_i \mid \pm 1)}{W_{new}(C_i)^r} - \frac{S(C_i) \mid C_i \mid }{W(C_i)^r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм состоит из следующих этапов:&lt;br /&gt;
&lt;br /&gt;
1. &#039;&#039;&#039;Инициализация&#039;&#039;&#039;. На этом этапе происходит первый проход по таблице с транзакциями для построения начального разбиения, для каждой транзакции определяется кластер исходя из максимизации стоимости.&lt;br /&gt;
&lt;br /&gt;
2. &#039;&#039;&#039;Итерация&#039;&#039;&#039;. На данном этапе для каждой транзакции проводится попытка перемещения в другой кластер для максимизации функции стоимости.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
[[File:InitIter.PNG||500px]]&lt;br /&gt;
&lt;br /&gt;
Первая часть алгоритма - инициализация: для каждой транзакции вычисляется кластер, к которому она будет отнесена исходя из максимизации функции стоимости. Для этого вычисляется вспомогательная функция DeltaAdd, которая считает стоимость добавления транзакции к одному из существующих кластеров, либо к пустому. В итоге транзакция помещается в кластер, для которого цена добавления максимальна.&lt;br /&gt;
&lt;br /&gt;
Вторая часть алгоритма - уточняющие итерации: здесь происходит попытка улучшить вычисленные на первом этапе кластеры. В каждой итерации происходит перебор всех транзакций, и для каждой транзакции вычисляется цена удаления ее из текущего кластера и цена добавления в другой кластер. Суммарная стоимость перемещения будет являться суммой стоимостей удаления и добавления. Если максимальная стоимость перемещения данной транзакции в какой-либо больше нуля, то она перемещается в этот кластер. &lt;br /&gt;
&lt;br /&gt;
Вычисления происходят до тех пор, пока за итерацию происходит хотя бы одно перемещение транзакции. Если за итерацию не было произведено ни одного перемещения, то текущее состояние кластеров является устойчивым и оптимальным. &amp;lt;ref&amp;gt;Павлин Н. Кластеризация категорийных данных: масштабируемый алгоритм CLOPE, https://basegroup.ru/community/articles/clope&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Схема реализации на псевдокоде:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Входные параметры:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - транзакции&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; - коэффициент отталкивания&lt;br /&gt;
&lt;br /&gt;
Выходной параметр:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; кластеры, в начале алгоритма - пустое множество&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация:&#039;&#039;&#039;&lt;br /&gt;
    &#039;&#039;&#039;for&#039;&#039;&#039; t_i in t:&lt;br /&gt;
    max = 0&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; C_j in C:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; DeltaAdd(C_j,t_i,r) &amp;gt; max:&lt;br /&gt;
                max = DeltaAdd(C_j,t_i,r)&lt;br /&gt;
                C_best = C_j&lt;br /&gt;
    &#039;&#039;&#039;put&#039;&#039;&#039; t_i in C_best&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Итерации:&#039;&#039;&#039;&lt;br /&gt;
    move = True&lt;br /&gt;
    &#039;&#039;&#039;while&#039;&#039;&#039; move == True:&lt;br /&gt;
    move = False&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; t_i in t:&lt;br /&gt;
            max = 0&lt;br /&gt;
            C_now = t_i.cluster&lt;br /&gt;
            removeCost = DeltaRemove(C_now,t_i,r)&lt;br /&gt;
            &#039;&#039;&#039;for&#039;&#039;&#039; C_j in C:&lt;br /&gt;
                &#039;&#039;&#039;if&#039;&#039;&#039; DeltaAdd(C_j,t_i,r) + removeCost &amp;gt; max:&lt;br /&gt;
                    max = DeltaAdd(C_j,t_i,r) + removeCost&lt;br /&gt;
                    C_best = C_j&lt;br /&gt;
        if max &amp;gt; 0&lt;br /&gt;
            &#039;&#039;&#039;del&#039;&#039;&#039; t_i from C_now&lt;br /&gt;
            &#039;&#039;&#039;put&#039;&#039;&#039; t_i in C_best&lt;br /&gt;
            move = True&lt;br /&gt;
&lt;br /&gt;
Вспомогательная функция &#039;&#039;&#039;DeltaAdd&#039;&#039;&#039;:&lt;br /&gt;
    &#039;&#039;&#039;function&#039;&#039;&#039; DeltaAdd(C,t,r)&lt;br /&gt;
        S_new=C.size + t.itemCount&lt;br /&gt;
        W_new=C.wigth&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; item in t_i:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; C_j.occ(item) = 0&lt;br /&gt;
                &#039;&#039;W_new = W_new + 1&lt;br /&gt;
        &#039;&#039;&#039;return&#039;&#039;&#039; S_new * (C.count+1) / (W_new ^ r) - (C.size * C.count) / (C.wigth ^ r)&lt;br /&gt;
&lt;br /&gt;
Вспомогательная функция &#039;&#039;&#039;DeltaRemove&#039;&#039;&#039;:&lt;br /&gt;
    &#039;&#039;&#039;function&#039;&#039;&#039; DeltaRemove(C,t,r)&lt;br /&gt;
        S_new=C.size - t.itemCount&lt;br /&gt;
        W_new=C.wigth&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; item in t:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; C_j.occ(item) = 1&lt;br /&gt;
                &#039;&#039;W_new = W_new - 1&lt;br /&gt;
        &#039;&#039;&#039;return&#039;&#039;&#039; S_new * (C.count-1) / (W_new ^ r) - (C.size * C.count) / (C.wigth ^ r)&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
В соответствии с ранее введенным обозначением &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - количество транзакций, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина транзакции(максимальная), &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество кластеров.&lt;br /&gt;
&lt;br /&gt;
Основные вычисления восполняются в функции DeltaAdd/DeltaRemove: производится 1 сложение, не более &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; сложений/вычитаний, 2 умножения, 2 деления, 2 возведения в степень и 1 сложение - итого &amp;lt;math&amp;gt;m + 8&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;k&amp;lt;/math&amp;gt; штук). Итого выполняется &amp;lt;math&amp;gt;n*k*(m+8)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
В добавок к этому при добавлении/удалении транзакции к кластеру производится пересчет его характеристик: &amp;lt;math&amp;gt;m+2&amp;lt;/math&amp;gt; операции.&lt;br /&gt;
&lt;br /&gt;
Из того можно сделать вывод, что оценка сложность алгоритма равна &amp;lt;math&amp;gt;O(n*k*m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
&lt;br /&gt;
На рисунке ниже представлена схема этапа инициализации на примере входной транзакции &#039;&#039;&#039;T&#039;&#039;&#039; и четырех кластеров &#039;&#039;&#039;Cl 1&#039;&#039;&#039;, &#039;&#039;&#039;Cl 2&#039;&#039;&#039;, &#039;&#039;&#039;Cl 3&#039;&#039;&#039; и &#039;&#039;&#039;Cl 4&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Объект &#039;&#039;&#039;DeltaAdd&#039;&#039;&#039; соответствует выполнению соответствующей функции для вычисления цены добавления транзакции на кластер. После выполнения всех &#039;&#039;&#039;DeltaAdd&#039;&#039;&#039; для одной транзакции выполняется определение максимального значения функции и выбор кластера, на который будет помещена транзакция. На этапе инициализации при обработке каждой транзакции количество кластеров может как увеличиться, так и остаться неизменным.&lt;br /&gt;
&lt;br /&gt;
[[File:InitDef.PNG||700px]]&lt;br /&gt;
&lt;br /&gt;
Этап итераций отличается только тем, что на нем дополнительно считается функция &#039;&#039;&#039;DeltaRemove&#039;&#039;&#039; вычисления стоимости удаления транзакции с кластера. На этапе итерации функции DeltaAdd/DeltaRemove могут считать параллельно для каждой транзакции.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Вычисление стоимости добавления/удаления транзакции, которые выполняются функциями DeltaAdd/DeltaRemove, происходит независимо для всех &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; кластеров. Поэтому все вычисления можно производить параллельно. Таким образом сложность алгоритма с &amp;lt;math&amp;gt;O(n*k*m)&amp;lt;/math&amp;gt; понижается до &amp;lt;math&amp;gt;O(n*m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; транзакций длины &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; и коэффициент отталкивания &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
метки классов для каждой транзакции в соответствии с проведенной кластеризацией(числовая последовательность длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной сложности алгоритма определяется количеством кластеров: &amp;lt;math&amp;gt;\dfrac{O(n*k*m)}{O(n*m)} = k&amp;lt;/math&amp;gt;&lt;br /&gt;
* [[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]] алгоритма равна &amp;lt;math&amp;gt;\dfrac{nk(m+8) + m + 2}{nm + n + 1} \cong k&amp;lt;/math&amp;gt;&lt;br /&gt;
* Алгоритм не является [[глоссарий#Устойчивость|&#039;&#039;устойчивым&#039;&#039;]], так как результат работы зависит от порядка чтения транзакций и от текущего набора транзакций в кластере.&lt;br /&gt;
* Выполняется свойство сбалансированности операций между параллельными ветвями алгоритма, так как для каждой транзакции выполняются функции DeltaAdd/DeltaRemove, считающие стоимость добавления/удаления транзакции.&lt;br /&gt;
* Свойство [[глоссарий#Детерминированность|&#039;&#039;детерминированности алгоритмов&#039;&#039;]] не выполняется, так как результат алгоритма зависит от порядка прохождения транзакций. Но если рассматривать транзакции как нумерованный список, то результат будет определен однозначно от запуска к запуску. Однако существует расширение алгоритма, обеспечивающее свойство детерминированности. &amp;lt;ref&amp;gt;Li, Y., Le, J., Wang, M. Improving CLOPE’s Profit Value and Stability with an Optimized Agglomerative Approach. Algorithms 2015, 8, 380-394.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
* Так как алгоритм предназначен для кластеризации категориальных данных, то он практически неприменим для числовой кластеризации.&lt;br /&gt;
* Быстро работает даже для большого количества данных, обеспечивая при этом хорошее качество кластеризации&lt;br /&gt;
* Имеет простую реализацию&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
Проверка масштабируемости проводилась на суперкомпьютере &amp;quot;Ломоносов&amp;quot; с числом процессоров 1, 8, 16, 32 и 64. Результаты проверки на графике ниже.&lt;br /&gt;
[[file:Graf_lom.png||700px]]&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
* http://weka.sourceforge.net/doc.stable/weka/clusterers/CLOPE.html - реализация в open source библиотеке для анализа данных WEKA(Waikato Environment for Knowledge Analysis) на языке Java&lt;br /&gt;
Также существуют пользовательские реализации алгоритма:&lt;br /&gt;
* https://github.com/infozor/php_mysql_clustering_clope - реализация алгоритма на PHP&lt;br /&gt;
* https://github.com/Tolsi/scala-clope - реализация алгоритма Scala&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:%D0%9F%D0%B0%D0%B2%D0%B5%D0%BB/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BA%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D0%B9%D0%BD%D1%8B%D1%85_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85_CLOPE&amp;diff=21598</id>
		<title>Участник:Павел/Алгоритм кластеризации категорийных данных CLOPE</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9F%D0%B0%D0%B2%D0%B5%D0%BB/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BA%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D0%B9%D0%BD%D1%8B%D1%85_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85_CLOPE&amp;diff=21598"/>
		<updated>2017-01-19T14:24:51Z</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;
Алгоритм CLOPE (Clustering with sLOPE&amp;lt;ref&amp;gt;Yang, Y., Guan, H., You. J. CLOPE: A fast and Effective Clustering Algorithm for Transactional Data In Proc. of SIGKDD’02, July 23-26, 2002, Edmonton, Alberta, Canada.&amp;lt;/ref&amp;gt;) неирархический метод кластеризации, предназначенный для кластеризации огромных наборов категорийных данных. К достоинствам алгоритма относятся высокие масштабируемость и скорость работы и качество кластеризации, что достигается использованием глобального критерия оптимизации на основе максимизации градиента высоты гистограммы кластера. Отличается простотой программной реализации. &lt;br /&gt;
&lt;br /&gt;
Во время работы алгоритм хранит в памяти небольшое количество информации по каждому кластеру и требует минимальное число сканирований набора данных. CLOPE автоматически подбирает количество кластеров, причем это регулируется одним единственным параметром - коэффициентом отталкивания &amp;lt;math&amp;gt; r &amp;lt;/math&amp;gt;. При этом он обеспечивает более высокую производительность и лучшее качество кластеризации в сравнении с многими иерархическими алгоритмами.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
Пусть имеется база транзакций &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, состоящая из множества транзакций &amp;lt;math&amp;gt;\{t_1,t_2,...,t_n\}&amp;lt;/math&amp;gt;. Каждая транзакция есть набор объектов &amp;lt;math&amp;gt;\{i_1,...,i_m\}&amp;lt;/math&amp;gt;. Множество кластеров &amp;lt;math&amp;gt;\{C_1,...,C_k\}&amp;lt;/math&amp;gt; есть разбиение множества &amp;lt;math&amp;gt;\{t_1,...,t_n\}&amp;lt;/math&amp;gt;, такое, что &amp;lt;math&amp;gt;C_1 \cup \dots \cup C_k=\{t_1,...,t_n\}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_i \ne \empty&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_i \cap C_j = \empty &amp;lt;/math&amp;gt;, для &amp;lt;math&amp;gt;i \ge 1, k \ge j&amp;lt;/math&amp;gt;. Каждый элемент &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; называется кластером, а &amp;lt;math&amp;gt;n, m, k&amp;lt;/math&amp;gt; – количество транзакций, количество объектов в базе транзакций и число кластеров соответственно.&lt;br /&gt;
&lt;br /&gt;
Каждый кластер &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; имеет следующие характеристики:&lt;br /&gt;
&amp;lt;math&amp;gt;D(C)&amp;lt;/math&amp;gt; – множество уникальных объектов;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;Occ(i,C)&amp;lt;/math&amp;gt; – количество вхождений (частота) объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; в кластер &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;S(C)= \sum_{i \in D(C)} Occ(i,C)= \sum_{t_i \in C}  \mid t_i  \mid , &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;W(C)=  \mid D(C) \mid ,H(C)=S(C)/W(C) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Функция стоимости:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; Profit(C) = \frac{\sum^{k}_{i=1} G(C_i) \times \mid C_i \mid} {\sum^{k}_{i=1} \mid C_i \mid } = \frac{\sum^{k}_{i=1} \frac{S(C_i)}{W(C_i)^r} \times \mid C_i \mid} {\sum^{k}_{i=1} \mid C_i \mid }  &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;\mid C_i \mid&amp;lt;/math&amp;gt;  количество объектов в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом кластере, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; – количество кластеров, &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; – коэффициент отталкивания &amp;lt;math&amp;gt;(0 &amp;lt; r \le 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С помощью параметра &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; регулируется уровень сходства транзакций внутри кластера, и, как&lt;br /&gt;
следствие, финальное количество кластеров. Этот коэффициент подбирается пользователем. Чем больше &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt;, тем ниже уровень сходства и тем больше кластеров будет сгенерировано.&lt;br /&gt;
&lt;br /&gt;
Постановка задачи кластеризации алгоритмом CLOPE выглядит следующим образом: &lt;br /&gt;
&lt;br /&gt;
для заданных &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; найти разбиение &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; такое, что: &lt;br /&gt;
&amp;lt;math&amp;gt;Profit(C) \longrightarrow max &amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит в вычислении на каждой итерации стоимости добавления и удаления транзакции из кластера: &lt;br /&gt;
&lt;br /&gt;
*вычисление нового размера кластера &amp;lt;math&amp;gt;S_{new}(C_i)=S(C_i) \pm \mid(t_n)\mid &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\mid(t_n)\mid&amp;lt;/math&amp;gt; - длина транзакции&lt;br /&gt;
&lt;br /&gt;
*вычисление новой ширины кластера &amp;lt;math&amp;gt;W_{new}(C_i)=\mid D(C_i \cup t_n)|&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*вычисление стоимости &amp;lt;math&amp;gt;\frac{S_{new}(C_i)(\mid C_i \mid \pm 1)}{W_{new}(C_i)^r} - \frac{S(C_i) \mid C_i \mid }{W(C_i)^r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм состоит из следующих этапов:&lt;br /&gt;
&lt;br /&gt;
1. &#039;&#039;&#039;Инициализация&#039;&#039;&#039;. На этом этапе происходит первый проход по таблице с транзакциями для построения начального разбиения, для каждой транзакции определяется кластер исходя из максимизации стоимости.&lt;br /&gt;
&lt;br /&gt;
2. &#039;&#039;&#039;Итерация&#039;&#039;&#039;. На данном этапе для каждой транзакции проводится попытка перемещения в другой кластер для максимизации функции стоимости.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Первая часть алгоритма - инициализация: для каждой транзакции вычисляется кластер, к которому она будет отнесена исходя из максимизации функции стоимости. Для этого вычисляется вспомогательная функция DeltaAdd, которая считает стоимость добавления транзакции к одному из существующих кластеров, либо к пустому. В итоге транзакция помещается в кластер, для которого цена добавления максимальна.&lt;br /&gt;
&lt;br /&gt;
Вторая часть алгоритма - уточняющие итерации: здесь происходит попытка улучшить вычисленные на первом этапе кластеры. В каждой итерации происходит перебор всех транзакций, и для каждой транзакции вычисляется цена удаления ее из текущего кластера и цена добавления в другой кластер. Суммарная стоимость перемещения будет являться суммой стоимостей удаления и добавления. Если максимальная стоимость перемещения данной транзакции в какой-либо больше нуля, то она перемещается в этот кластер. &lt;br /&gt;
&lt;br /&gt;
Вычисления происходят до тех пор, пока за итерацию происходит хотя бы одно перемещение транзакции. Если за итерацию не было произведено ни одного перемещения, то текущее состояние кластеров является устойчивым и оптимальным. &amp;lt;ref&amp;gt;Павлин Н. Кластеризация категорийных данных: масштабируемый алгоритм CLOPE, https://basegroup.ru/community/articles/clope&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Схема реализации на псевдокоде:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Входные параметры:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - транзакции&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; - коэффициент отталкивания&lt;br /&gt;
&lt;br /&gt;
Выходной параметр:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; кластеры, в начале алгоритма - пустое множество&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация:&#039;&#039;&#039;&lt;br /&gt;
    &#039;&#039;&#039;for&#039;&#039;&#039; t_i in t:&lt;br /&gt;
    max = 0&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; C_j in C:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; DeltaAdd(C_j,t_i,r) &amp;gt; max:&lt;br /&gt;
                max = DeltaAdd(C_j,t_i,r)&lt;br /&gt;
                C_best = C_j&lt;br /&gt;
    &#039;&#039;&#039;put&#039;&#039;&#039; t_i in C_best&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Итерации:&#039;&#039;&#039;&lt;br /&gt;
    move = True&lt;br /&gt;
    &#039;&#039;&#039;while&#039;&#039;&#039; move == True:&lt;br /&gt;
    move = False&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; t_i in t:&lt;br /&gt;
            max = 0&lt;br /&gt;
            C_now = t_i.cluster&lt;br /&gt;
            removeCost = DeltaRemove(C_now,t_i,r)&lt;br /&gt;
            &#039;&#039;&#039;for&#039;&#039;&#039; C_j in C:&lt;br /&gt;
                &#039;&#039;&#039;if&#039;&#039;&#039; DeltaAdd(C_j,t_i,r) + removeCost &amp;gt; max:&lt;br /&gt;
                    max = DeltaAdd(C_j,t_i,r) + removeCost&lt;br /&gt;
                    C_best = C_j&lt;br /&gt;
        if max &amp;gt; 0&lt;br /&gt;
            &#039;&#039;&#039;del&#039;&#039;&#039; t_i from C_now&lt;br /&gt;
            &#039;&#039;&#039;put&#039;&#039;&#039; t_i in C_best&lt;br /&gt;
            move = True&lt;br /&gt;
&lt;br /&gt;
Вспомогательная функция &#039;&#039;&#039;DeltaAdd&#039;&#039;&#039;:&lt;br /&gt;
    &#039;&#039;&#039;function&#039;&#039;&#039; DeltaAdd(C,t,r)&lt;br /&gt;
        S_new=C.size + t.itemCount&lt;br /&gt;
        W_new=C.wigth&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; item in t_i:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; C_j.occ(item) = 0&lt;br /&gt;
                &#039;&#039;W_new = W_new + 1&lt;br /&gt;
        &#039;&#039;&#039;return&#039;&#039;&#039; S_new * (C.count+1) / (W_new ^ r) - (C.size * C.count) / (C.wigth ^ r)&lt;br /&gt;
&lt;br /&gt;
Вспомогательная функция &#039;&#039;&#039;DeltaRemove&#039;&#039;&#039;:&lt;br /&gt;
    &#039;&#039;&#039;function&#039;&#039;&#039; DeltaRemove(C,t,r)&lt;br /&gt;
        S_new=C.size - t.itemCount&lt;br /&gt;
        W_new=C.wigth&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; item in t:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; C_j.occ(item) = 1&lt;br /&gt;
                &#039;&#039;W_new = W_new - 1&lt;br /&gt;
        &#039;&#039;&#039;return&#039;&#039;&#039; S_new * (C.count-1) / (W_new ^ r) - (C.size * C.count) / (C.wigth ^ r)&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
В соответствии с ранее введенным обозначением &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - количество транзакций, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина транзакции(максимальная), &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество кластеров.&lt;br /&gt;
&lt;br /&gt;
Основные вычисления восполняются в функции DeltaAdd/DeltaRemove: производится 1 сложение, не более &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; сложений/вычитаний, 2 умножения, 2 деления, 2 возведения в степень и 1 сложение - итого &amp;lt;math&amp;gt;m + 8&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;k&amp;lt;/math&amp;gt; штук). Итого выполняется &amp;lt;math&amp;gt;n*k*(m+8)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
В добавок к этому при добавлении/удалении транзакции к кластеру производится пересчет его характеристик: &amp;lt;math&amp;gt;m+2&amp;lt;/math&amp;gt; операции.&lt;br /&gt;
&lt;br /&gt;
Из того можно сделать вывод, что оценка сложность алгоритма равна &amp;lt;math&amp;gt;O(n*k*m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
&lt;br /&gt;
На рисунке ниже представлена схема этапа инициализации на примере входной транзакции &#039;&#039;&#039;T&#039;&#039;&#039; и четырех кластеров &#039;&#039;&#039;Cl 1&#039;&#039;&#039;, &#039;&#039;&#039;Cl 2&#039;&#039;&#039;, &#039;&#039;&#039;Cl 3&#039;&#039;&#039; и &#039;&#039;&#039;Cl 4&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Объект &#039;&#039;&#039;DeltaAdd&#039;&#039;&#039; соответствует выполнению соответствующей функции для вычисления цены добавления транзакции на кластер. После выполнения всех &#039;&#039;&#039;DeltaAdd&#039;&#039;&#039; для одной транзакции выполняется определение максимального значения функции и выбор кластера, на который будет помещена транзакция. На этапе инициализации при обработке каждой транзакции количество кластеров может как увеличиться, так и остаться неизменным.&lt;br /&gt;
&lt;br /&gt;
[[File:InitDef.PNG||700px]]&lt;br /&gt;
&lt;br /&gt;
Этап итераций отличается только тем, что на нем дополнительно считается функция &#039;&#039;&#039;DeltaRemove&#039;&#039;&#039; вычисления стоимости удаления транзакции с кластера. На этапе итерации функции DeltaAdd/DeltaRemove могут считать параллельно для каждой транзакции.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Вычисление стоимости добавления/удаления транзакции, которые выполняются функциями DeltaAdd/DeltaRemove, происходит независимо для всех &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; кластеров. Поэтому все вычисления можно производить параллельно. Таким образом сложность алгоритма с &amp;lt;math&amp;gt;O(n*k*m)&amp;lt;/math&amp;gt; понижается до &amp;lt;math&amp;gt;O(n*m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; транзакций длины &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; и коэффициент отталкивания &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
метки классов для каждой транзакции в соответствии с проведенной кластеризацией(числовая последовательность длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной сложности алгоритма определяется количеством кластеров: &amp;lt;math&amp;gt;\dfrac{O(n*k*m)}{O(n*m)} = k&amp;lt;/math&amp;gt;&lt;br /&gt;
* [[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]] алгоритма равна &amp;lt;math&amp;gt;\dfrac{nk(m+8) + m + 2}{nm + n + 1} \cong k&amp;lt;/math&amp;gt;&lt;br /&gt;
* Алгоритм не является [[глоссарий#Устойчивость|&#039;&#039;устойчивым&#039;&#039;]], так как результат работы зависит от порядка чтения транзакций и от текущего набора транзакций в кластере.&lt;br /&gt;
* Выполняется свойство сбалансированности операций между параллельными ветвями алгоритма, так как для каждой транзакции выполняются функции DeltaAdd/DeltaRemove, считающие стоимость добавления/удаления транзакции.&lt;br /&gt;
* Свойство [[глоссарий#Детерминированность|&#039;&#039;детерминированности алгоритмов&#039;&#039;]] не выполняется, так как результат алгоритма зависит от порядка прохождения транзакций. Но если рассматривать транзакции как нумерованный список, то результат будет определен однозначно от запуска к запуску. Однако существует расширение алгоритма, обеспечивающее свойство детерминированности. &amp;lt;ref&amp;gt;Li, Y., Le, J., Wang, M. Improving CLOPE’s Profit Value and Stability with an Optimized Agglomerative Approach. Algorithms 2015, 8, 380-394.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
* Так как алгоритм предназначен для кластеризации категориальных данных, то он практически неприменим для числовой кластеризации.&lt;br /&gt;
* Быстро работает даже для большого количества данных, обеспечивая при этом хорошее качество кластеризации&lt;br /&gt;
* Имеет простую реализацию&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
Проверка масштабируемости проводилась на суперкомпьютере &amp;quot;Ломоносов&amp;quot; с числом процессоров 1, 8, 16, 32 и 64. Результаты проверки на графике ниже.&lt;br /&gt;
[[file:Graf_lom.png||700px]]&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
* http://weka.sourceforge.net/doc.stable/weka/clusterers/CLOPE.html - реализация в open source библиотеке для анализа данных WEKA(Waikato Environment for Knowledge Analysis) на языке Java&lt;br /&gt;
Также существуют пользовательские реализации алгоритма:&lt;br /&gt;
* https://github.com/infozor/php_mysql_clustering_clope - реализация алгоритма на PHP&lt;br /&gt;
* https://github.com/Tolsi/scala-clope - реализация алгоритма Scala&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:%D0%9F%D0%B0%D0%B2%D0%B5%D0%BB/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BA%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D0%B9%D0%BD%D1%8B%D1%85_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85_CLOPE&amp;diff=21596</id>
		<title>Участник:Павел/Алгоритм кластеризации категорийных данных CLOPE</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9F%D0%B0%D0%B2%D0%B5%D0%BB/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BA%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D0%B9%D0%BD%D1%8B%D1%85_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85_CLOPE&amp;diff=21596"/>
		<updated>2017-01-19T14:21:54Z</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;
Алгоритм CLOPE (Clustering with sLOPE&amp;lt;ref&amp;gt;Yang, Y., Guan, H., You. J. CLOPE: A fast and Effective Clustering Algorithm for Transactional Data In Proc. of SIGKDD’02, July 23-26, 2002, Edmonton, Alberta, Canada.&amp;lt;/ref&amp;gt;) неирархический метод кластеризации, предназначенный для кластеризации огромных наборов категорийных данных. К достоинствам алгоритма относятся высокие масштабируемость и скорость работы и качество кластеризации, что достигается использованием глобального критерия оптимизации на основе максимизации градиента высоты гистограммы кластера. Отличается простотой программной реализации. &lt;br /&gt;
&lt;br /&gt;
Во время работы алгоритм хранит в памяти небольшое количество информации по каждому кластеру и требует минимальное число сканирований набора данных. CLOPE автоматически подбирает количество кластеров, причем это регулируется одним единственным параметром - коэффициентом отталкивания &amp;lt;math&amp;gt; r &amp;lt;/math&amp;gt;. При этом он обеспечивает более высокую производительность и лучшее качество кластеризации в сравнении с многими иерархическими алгоритмами.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
Пусть имеется база транзакций &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, состоящая из множества транзакций &amp;lt;math&amp;gt;\{t_1,t_2,...,t_n\}&amp;lt;/math&amp;gt;. Каждая транзакция есть набор объектов &amp;lt;math&amp;gt;\{i_1,...,i_m\}&amp;lt;/math&amp;gt;. Множество кластеров &amp;lt;math&amp;gt;\{C_1,...,C_k\}&amp;lt;/math&amp;gt; есть разбиение множества &amp;lt;math&amp;gt;\{t_1,...,t_n\}&amp;lt;/math&amp;gt;, такое, что &amp;lt;math&amp;gt;C_1 \cup \dots \cup C_k=\{t_1,...,t_n\}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_i \ne \empty&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_i \cap C_j = \empty &amp;lt;/math&amp;gt;, для &amp;lt;math&amp;gt;i \ge 1, k \ge j&amp;lt;/math&amp;gt;. Каждый элемент &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; называется кластером, а &amp;lt;math&amp;gt;n, m, k&amp;lt;/math&amp;gt; – количество транзакций, количество объектов в базе транзакций и число кластеров соответственно.&lt;br /&gt;
&lt;br /&gt;
Каждый кластер &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; имеет следующие характеристики:&lt;br /&gt;
&amp;lt;math&amp;gt;D(C)&amp;lt;/math&amp;gt; – множество уникальных объектов;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;Occ(i,C)&amp;lt;/math&amp;gt; – количество вхождений (частота) объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; в кластер &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;S(C)= \sum_{i \in D(C)} Occ(i,C)= \sum_{t_i \in C}  \mid t_i  \mid , &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;W(C)=  \mid D(C) \mid ,H(C)=S(C)/W(C) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Функция стоимости:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; Profit(C) = \frac{\sum^{k}_{i=1} G(C_i) \times \mid C_i \mid} {\sum^{k}_{i=1} \mid C_i \mid } = \frac{\sum^{k}_{i=1} \frac{S(C_i)}{W(C_i)^r} \times \mid C_i \mid} {\sum^{k}_{i=1} \mid C_i \mid }  &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;\mid C_i \mid&amp;lt;/math&amp;gt;  количество объектов в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом кластере, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; – количество кластеров, &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; – коэффициент отталкивания &amp;lt;math&amp;gt;(0 &amp;lt; r \le 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С помощью параметра &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; регулируется уровень сходства транзакций внутри кластера, и, как&lt;br /&gt;
следствие, финальное количество кластеров. Этот коэффициент подбирается пользователем. Чем больше &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt;, тем ниже уровень сходства и тем больше кластеров будет сгенерировано.&lt;br /&gt;
&lt;br /&gt;
Постановка задачи кластеризации алгоритмом CLOPE выглядит следующим образом: &lt;br /&gt;
&lt;br /&gt;
для заданных &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; найти разбиение &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; такое, что: &lt;br /&gt;
&amp;lt;math&amp;gt;Profit(C) \longrightarrow max &amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит в вычислении на каждой итерации стоимости добавления и удаления транзакции из кластера: &lt;br /&gt;
&lt;br /&gt;
*вычисление нового размера кластера &amp;lt;math&amp;gt;S_{new}(C_i)=S(C_i) \pm \mid(t_n)\mid &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\mid(t_n)\mid&amp;lt;/math&amp;gt; - длина транзакции&lt;br /&gt;
&lt;br /&gt;
*вычисление новой ширины кластера &amp;lt;math&amp;gt;W_{new}(C_i)=\mid D(C_i \cup t_n)|&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*вычисление стоимости &amp;lt;math&amp;gt;\frac{S_{new}(C_i)(\mid C_i \mid \pm 1)}{W_{new}(C_i)^r} - \frac{S(C_i) \mid C_i \mid }{W(C_i)^r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм состоит из следующих этапов:&lt;br /&gt;
&lt;br /&gt;
1. &#039;&#039;&#039;Инициализация&#039;&#039;&#039;. На этом этапе происходит первый проход по таблице с транзакциями для построения начального разбиения, для каждой транзакции определяется кластер исходя из максимизации стоимости.&lt;br /&gt;
&lt;br /&gt;
2. &#039;&#039;&#039;Итерация&#039;&#039;&#039;. На данном этапе для каждой транзакции проводится попытка перемещения в другой кластер для максимизации функции стоимости.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Первая часть алгоритма - инициализация: для каждой транзакции вычисляется кластер, к которому она будет отнесена исходя из максимизации функции стоимости. Для этого вычисляется вспомогательная функция DeltaAdd, которая считает стоимость добавления транзакции к одному из существующих кластеров, либо к пустому. В итоге транзакция помещается в кластер, для которого цена добавления максимальна.&lt;br /&gt;
&lt;br /&gt;
Вторая часть алгоритма - уточняющие итерации: здесь происходит попытка улучшить вычисленные на первом этапе кластеры. В каждой итерации происходит перебор всех транзакций, и для каждой транзакции вычисляется цена удаления ее из текущего кластера и цена добавления в другой кластер. Суммарная стоимость перемещения будет являться суммой стоимостей удаления и добавления. Если максимальная стоимость перемещения данной транзакции в какой-либо больше нуля, то она перемещается в этот кластер. &lt;br /&gt;
&lt;br /&gt;
Вычисления происходят до тех пор, пока за итерацию происходит хотя бы одно перемещение транзакции. Если за итерацию не было произведено ни одного перемещения, то текущее состояние кластеров является устойчивым и оптимальным. &amp;lt;ref&amp;gt;Павлин Н. Кластеризация категорийных данных: масштабируемый алгоритм CLOPE, https://basegroup.ru/community/articles/clope&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Схема реализации на псевдокоде:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Входные параметры:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - транзакции&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; - коэффициент отталкивания&lt;br /&gt;
&lt;br /&gt;
Выходной параметр:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; кластеры, в начале алгоритма - пустое множество&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация:&#039;&#039;&#039;&lt;br /&gt;
    &#039;&#039;&#039;for&#039;&#039;&#039; t_i in t:&lt;br /&gt;
    max = 0&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; C_j in C:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; DeltaAdd(C_j,t_i,r) &amp;gt; max:&lt;br /&gt;
                max = DeltaAdd(C_j,t_i,r)&lt;br /&gt;
                C_best = C_j&lt;br /&gt;
    &#039;&#039;&#039;put&#039;&#039;&#039; t_i in C_best&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Итерации:&#039;&#039;&#039;&lt;br /&gt;
    move = True&lt;br /&gt;
    &#039;&#039;&#039;while&#039;&#039;&#039; move == True:&lt;br /&gt;
    move = False&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; t_i in t:&lt;br /&gt;
            max = 0&lt;br /&gt;
            C_now = t_i.cluster&lt;br /&gt;
            removeCost = DeltaRemove(C_now,t_i,r)&lt;br /&gt;
            &#039;&#039;&#039;for&#039;&#039;&#039; C_j in C:&lt;br /&gt;
                &#039;&#039;&#039;if&#039;&#039;&#039; DeltaAdd(C_j,t_i,r) + removeCost &amp;gt; max:&lt;br /&gt;
                    max = DeltaAdd(C_j,t_i,r) + removeCost&lt;br /&gt;
                    C_best = C_j&lt;br /&gt;
        if max &amp;gt; 0&lt;br /&gt;
            &#039;&#039;&#039;del&#039;&#039;&#039; t_i from C_now&lt;br /&gt;
            &#039;&#039;&#039;put&#039;&#039;&#039; t_i in C_best&lt;br /&gt;
            move = True&lt;br /&gt;
&lt;br /&gt;
Вспомогательная функция &#039;&#039;&#039;DeltaAdd&#039;&#039;&#039;:&lt;br /&gt;
    &#039;&#039;&#039;function&#039;&#039;&#039; DeltaAdd(C,t,r)&lt;br /&gt;
        S_new=C.size + t.itemCount&lt;br /&gt;
        W_new=C.wigth&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; item in t_i:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; C_j.occ(item) = 0&lt;br /&gt;
                &#039;&#039;W_new = W_new + 1&lt;br /&gt;
        &#039;&#039;&#039;return&#039;&#039;&#039; S_new * (C.count+1) / (W_new ^ r) - (C.size * C.count) / (C.wigth ^ r)&lt;br /&gt;
&lt;br /&gt;
Вспомогательная функция &#039;&#039;&#039;DeltaRemove&#039;&#039;&#039;:&lt;br /&gt;
    &#039;&#039;&#039;function&#039;&#039;&#039; DeltaRemove(C,t,r)&lt;br /&gt;
        S_new=C.size - t.itemCount&lt;br /&gt;
        W_new=C.wigth&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; item in t:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; C_j.occ(item) = 1&lt;br /&gt;
                &#039;&#039;W_new = W_new - 1&lt;br /&gt;
        &#039;&#039;&#039;return&#039;&#039;&#039; S_new * (C.count-1) / (W_new ^ r) - (C.size * C.count) / (C.wigth ^ r)&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
В соответствии с ранее введенным обозначением &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - количество транзакций, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина транзакции(максимальная), &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество кластеров.&lt;br /&gt;
&lt;br /&gt;
Основные вычисления восполняются в функции DeltaAdd/DeltaRemove: производится 1 сложение, не более &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; сложений/вычитаний, 2 умножения, 2 деления, 2 возведения в степень и 1 сложение - итого &amp;lt;math&amp;gt;m + 8&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;k&amp;lt;/math&amp;gt; штук). Итого выполняется &amp;lt;math&amp;gt;n*k*(m+8)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
В добавок к этому при добавлении/удалении транзакции к кластеру производится пересчет его характеристик: &amp;lt;math&amp;gt;m+2&amp;lt;/math&amp;gt; операции.&lt;br /&gt;
&lt;br /&gt;
Из того можно сделать вывод, что оценка сложность алгоритма равна &amp;lt;math&amp;gt;O(n*k*m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
&lt;br /&gt;
Объект &#039;&#039;&#039;DeltaAdd&#039;&#039;&#039; соответствует выполнению соответствующей функции для вычисления цены добавления транзакции на кластер. После выполнения всех &#039;&#039;&#039;DeltaAdd&#039;&#039;&#039; для одной транзакции выполняется определение максимального значения функции и выбор кластера, на который будет помещена транзакция. На этапе инициализации при обработке каждой транзакции количество кластеров может как увеличиться, так и остаться неизменным.&lt;br /&gt;
&lt;br /&gt;
[[File:InitDef.PNG||700px]]&lt;br /&gt;
&lt;br /&gt;
Этап итераций отличается только тем, что на нем дополнительно считается функция &#039;&#039;&#039;DeltaRemove&#039;&#039;&#039; вычисления стоимости удаления транзакции с кластера. На этапе итерации функции DeltaAdd/DeltaRemove могут считать параллельно для каждой транзакции.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Вычисление стоимости добавления/удаления транзакции, которые выполняются функциями DeltaAdd/DeltaRemove, происходит независимо для всех &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; кластеров. Поэтому все вычисления можно производить параллельно. Таким образом сложность алгоритма с &amp;lt;math&amp;gt;O(n*k*m)&amp;lt;/math&amp;gt; понижается до &amp;lt;math&amp;gt;O(n*m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; транзакций длины &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; и коэффициент отталкивания &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
метки классов для каждой транзакции в соответствии с проведенной кластеризацией(числовая последовательность длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной сложности алгоритма определяется количеством кластеров: &amp;lt;math&amp;gt;\dfrac{O(n*k*m)}{O(n*m)} = k&amp;lt;/math&amp;gt;&lt;br /&gt;
* [[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]] алгоритма равна &amp;lt;math&amp;gt;\dfrac{nk(m+8) + m + 2}{nm + n + 1} \cong k&amp;lt;/math&amp;gt;&lt;br /&gt;
* Алгоритм не является [[глоссарий#Устойчивость|&#039;&#039;устойчивым&#039;&#039;]], так как результат работы зависит от порядка чтения транзакций и от текущего набора транзакций в кластере.&lt;br /&gt;
* Выполняется свойство сбалансированности операций между параллельными ветвями алгоритма, так как для каждой транзакции выполняются функции DeltaAdd/DeltaRemove, считающие стоимость добавления/удаления транзакции.&lt;br /&gt;
* Свойство [[глоссарий#Детерминированность|&#039;&#039;детерминированности алгоритмов&#039;&#039;]] не выполняется, так как результат алгоритма зависит от порядка прохождения транзакций. Но если рассматривать транзакции как нумерованный список, то результат будет определен однозначно от запуска к запуску. Однако существует расширение алгоритма, обеспечивающее свойство детерминированности. &amp;lt;ref&amp;gt;Li, Y., Le, J., Wang, M. Improving CLOPE’s Profit Value and Stability with an Optimized Agglomerative Approach. Algorithms 2015, 8, 380-394.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
* Так как алгоритм предназначен для кластеризации категориальных данных, то он практически неприменим для числовой кластеризации.&lt;br /&gt;
* Быстро работает даже для большого количества данных, обеспечивая при этом хорошее качество кластеризации&lt;br /&gt;
* Имеет простую реализацию&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
Проверка масштабируемости проводилась на суперкомпьютере &amp;quot;Ломоносов&amp;quot; с числом процессоров 1, 8, 16, 32 и 64. Результаты проверки на графике ниже.&lt;br /&gt;
[[file:Graf_lom.png||700px]]&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
* http://weka.sourceforge.net/doc.stable/weka/clusterers/CLOPE.html - реализация в open source библиотеке для анализа данных WEKA(Waikato Environment for Knowledge Analysis) на языке Java&lt;br /&gt;
Также существуют пользовательские реализации алгоритма:&lt;br /&gt;
* https://github.com/infozor/php_mysql_clustering_clope - реализация алгоритма на PHP&lt;br /&gt;
* https://github.com/Tolsi/scala-clope - реализация алгоритма Scala&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:%D0%9F%D0%B0%D0%B2%D0%B5%D0%BB/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BA%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D0%B9%D0%BD%D1%8B%D1%85_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85_CLOPE&amp;diff=21593</id>
		<title>Участник:Павел/Алгоритм кластеризации категорийных данных CLOPE</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9F%D0%B0%D0%B2%D0%B5%D0%BB/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BA%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D0%B9%D0%BD%D1%8B%D1%85_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85_CLOPE&amp;diff=21593"/>
		<updated>2017-01-19T14:07: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;
Алгоритм CLOPE (Clustering with sLOPE&amp;lt;ref&amp;gt;Yang, Y., Guan, H., You. J. CLOPE: A fast and Effective Clustering Algorithm for Transactional Data In Proc. of SIGKDD’02, July 23-26, 2002, Edmonton, Alberta, Canada.&amp;lt;/ref&amp;gt;) неирархический метод кластеризации, предназначенный для кластеризации огромных наборов категорийных данных. К достоинствам алгоритма относятся высокие масштабируемость и скорость работы и качество кластеризации, что достигается использованием глобального критерия оптимизации на основе максимизации градиента высоты гистограммы кластера. Отличается простотой программной реализации. &lt;br /&gt;
&lt;br /&gt;
Во время работы алгоритм хранит в памяти небольшое количество информации по каждому кластеру и требует минимальное число сканирований набора данных. CLOPE автоматически подбирает количество кластеров, причем это регулируется одним единственным параметром - коэффициентом отталкивания &amp;lt;math&amp;gt; r &amp;lt;/math&amp;gt;. При этом он обеспечивает более высокую производительность и лучшее качество кластеризации в сравнении с многими иерархическими алгоритмами.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
Пусть имеется база транзакций &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, состоящая из множества транзакций &amp;lt;math&amp;gt;\{t_1,t_2,...,t_n\}&amp;lt;/math&amp;gt;. Каждая транзакция есть набор объектов &amp;lt;math&amp;gt;\{i_1,...,i_m\}&amp;lt;/math&amp;gt;. Множество кластеров &amp;lt;math&amp;gt;\{C_1,...,C_k\}&amp;lt;/math&amp;gt; есть разбиение множества &amp;lt;math&amp;gt;\{t_1,...,t_n\}&amp;lt;/math&amp;gt;, такое, что &amp;lt;math&amp;gt;C_1 \cup \dots \cup C_k=\{t_1,...,t_n\}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_i \ne \empty&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_i \cap C_j = \empty &amp;lt;/math&amp;gt;, для &amp;lt;math&amp;gt;i \ge 1, k \ge j&amp;lt;/math&amp;gt;. Каждый элемент &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; называется кластером, а &amp;lt;math&amp;gt;n, m, k&amp;lt;/math&amp;gt; – количество транзакций, количество объектов в базе транзакций и число кластеров соответственно.&lt;br /&gt;
&lt;br /&gt;
Каждый кластер &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; имеет следующие характеристики:&lt;br /&gt;
&amp;lt;math&amp;gt;D(C)&amp;lt;/math&amp;gt; – множество уникальных объектов;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;Occ(i,C)&amp;lt;/math&amp;gt; – количество вхождений (частота) объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; в кластер &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;S(C)= \sum_{i \in D(C)} Occ(i,C)= \sum_{t_i \in C}  \mid t_i  \mid , &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;W(C)=  \mid D(C) \mid ,H(C)=S(C)/W(C) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Функция стоимости:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; Profit(C) = \frac{\sum^{k}_{i=1} G(C_i) \times \mid C_i \mid} {\sum^{k}_{i=1} \mid C_i \mid } = \frac{\sum^{k}_{i=1} \frac{S(C_i)}{W(C_i)^r} \times \mid C_i \mid} {\sum^{k}_{i=1} \mid C_i \mid }  &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;\mid C_i \mid&amp;lt;/math&amp;gt;  количество объектов в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом кластере, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; – количество кластеров, &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; – коэффициент отталкивания &amp;lt;math&amp;gt;(0 &amp;lt; r \le 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С помощью параметра &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; регулируется уровень сходства транзакций внутри кластера, и, как&lt;br /&gt;
следствие, финальное количество кластеров. Этот коэффициент подбирается пользователем. Чем больше &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt;, тем ниже уровень сходства и тем больше кластеров будет сгенерировано.&lt;br /&gt;
&lt;br /&gt;
Постановка задачи кластеризации алгоритмом CLOPE выглядит следующим образом: &lt;br /&gt;
&lt;br /&gt;
для заданных &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; найти разбиение &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; такое, что: &lt;br /&gt;
&amp;lt;math&amp;gt;Profit(C) \longrightarrow max &amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит в вычислении на каждой итерации стоимости добавления и удаления транзакции из кластера: &lt;br /&gt;
&lt;br /&gt;
*вычисление нового размера кластера &amp;lt;math&amp;gt;S_{new}(C_i)=S(C_i) \pm \mid(t_n)\mid &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\mid(t_n)\mid&amp;lt;/math&amp;gt; - длина транзакции&lt;br /&gt;
&lt;br /&gt;
*вычисление новой ширины кластера &amp;lt;math&amp;gt;W_{new}(C_i)=\mid D(C_i \cup t_n)|&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*вычисление стоимости &amp;lt;math&amp;gt;\frac{S_{new}(C_i)(\mid C_i \mid \pm 1)}{W_{new}(C_i)^r} - \frac{S(C_i) \mid C_i \mid }{W(C_i)^r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм состоит из следующих этапов:&lt;br /&gt;
&lt;br /&gt;
1. &#039;&#039;&#039;Инициализация&#039;&#039;&#039;. На этом этапе происходит первый проход по таблице с транзакциями для построения начального разбиения, для каждой транзакции определяется кластер исходя из максимизации стоимости.&lt;br /&gt;
&lt;br /&gt;
2. &#039;&#039;&#039;Итерация&#039;&#039;&#039;. На данном этапе для каждой транзакции проводится попытка перемещения в другой кластер для максимизации функции стоимости.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Первая часть алгоритма - инициализация: для каждой транзакции вычисляется кластер, к которому она будет отнесена исходя из максимизации функции стоимости. Для этого вычисляется вспомогательная функция DeltaAdd, которая считает стоимость добавления транзакции к одному из существующих кластеров, либо к пустому. В итоге транзакция помещается в кластер, для которого цена добавления максимальна.&lt;br /&gt;
&lt;br /&gt;
Вторая часть алгоритма - уточняющие итерации: здесь происходит попытка улучшить вычисленные на первом этапе кластеры. В каждой итерации происходит перебор всех транзакций, и для каждой транзакции вычисляется цена удаления ее из текущего кластера и цена добавления в другой кластер. Суммарная стоимость перемещения будет являться суммой стоимостей удаления и добавления. Если максимальная стоимость перемещения данной транзакции в какой-либо больше нуля, то она перемещается в этот кластер. &lt;br /&gt;
&lt;br /&gt;
Вычисления происходят до тех пор, пока за итерацию происходит хотя бы одно перемещение транзакции. Если за итерацию не было произведено ни одного перемещения, то текущее состояние кластеров является устойчивым и оптимальным. &amp;lt;ref&amp;gt;Павлин Н. Кластеризация категорийных данных: масштабируемый алгоритм CLOPE, https://basegroup.ru/community/articles/clope&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Схема реализации на псевдокоде:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Входные параметры:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - транзакции&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; - коэффициент отталкивания&lt;br /&gt;
&lt;br /&gt;
Выходной параметр:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; кластеры, в начале алгоритма - пустое множество&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация:&#039;&#039;&#039;&lt;br /&gt;
    &#039;&#039;&#039;for&#039;&#039;&#039; t_i in t:&lt;br /&gt;
    max = 0&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; C_j in C:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; DeltaAdd(C_j,t_i,r) &amp;gt; max:&lt;br /&gt;
                max = DeltaAdd(C_j,t_i,r)&lt;br /&gt;
                C_best = C_j&lt;br /&gt;
    &#039;&#039;&#039;put&#039;&#039;&#039; t_i in C_best&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Итерации:&#039;&#039;&#039;&lt;br /&gt;
    move = True&lt;br /&gt;
    &#039;&#039;&#039;while&#039;&#039;&#039; move == True:&lt;br /&gt;
    move = False&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; t_i in t:&lt;br /&gt;
            max = 0&lt;br /&gt;
            C_now = t_i.cluster&lt;br /&gt;
            removeCost = DeltaRemove(C_now,t_i,r)&lt;br /&gt;
            &#039;&#039;&#039;for&#039;&#039;&#039; C_j in C:&lt;br /&gt;
                &#039;&#039;&#039;if&#039;&#039;&#039; DeltaAdd(C_j,t_i,r) + removeCost &amp;gt; max:&lt;br /&gt;
                    max = DeltaAdd(C_j,t_i,r) + removeCost&lt;br /&gt;
                    C_best = C_j&lt;br /&gt;
        if max &amp;gt; 0&lt;br /&gt;
            &#039;&#039;&#039;del&#039;&#039;&#039; t_i from C_now&lt;br /&gt;
            &#039;&#039;&#039;put&#039;&#039;&#039; t_i in C_best&lt;br /&gt;
            move = True&lt;br /&gt;
&lt;br /&gt;
Вспомогательная функция &#039;&#039;&#039;DeltaAdd&#039;&#039;&#039;:&lt;br /&gt;
    &#039;&#039;&#039;function&#039;&#039;&#039; DeltaAdd(C,t,r)&lt;br /&gt;
        S_new=C.size + t.itemCount&lt;br /&gt;
        W_new=C.wigth&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; item in t_i:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; C_j.occ(item) = 0&lt;br /&gt;
                &#039;&#039;W_new = W_new + 1&lt;br /&gt;
        &#039;&#039;&#039;return&#039;&#039;&#039; S_new * (C.count+1) / (W_new ^ r) - (C.size * C.count) / (C.wigth ^ r)&lt;br /&gt;
&lt;br /&gt;
Вспомогательная функция &#039;&#039;&#039;DeltaRemove&#039;&#039;&#039;:&lt;br /&gt;
    &#039;&#039;&#039;function&#039;&#039;&#039; DeltaRemove(C,t,r)&lt;br /&gt;
        S_new=C.size - t.itemCount&lt;br /&gt;
        W_new=C.wigth&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; item in t:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; C_j.occ(item) = 1&lt;br /&gt;
                &#039;&#039;W_new = W_new - 1&lt;br /&gt;
        &#039;&#039;&#039;return&#039;&#039;&#039; S_new * (C.count-1) / (W_new ^ r) - (C.size * C.count) / (C.wigth ^ r)&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
В соответствии с ранее введенным обозначением &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - количество транзакций, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина транзакции(максимальная), &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество кластеров.&lt;br /&gt;
&lt;br /&gt;
Основные вычисления восполняются в функции DeltaAdd/DeltaRemove: производится 1 сложение, не более &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; сложений/вычитаний, 2 умножения, 2 деления, 2 возведения в степень и 1 сложение - итого &amp;lt;math&amp;gt;m + 8&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;k&amp;lt;/math&amp;gt; штук). Итого выполняется &amp;lt;math&amp;gt;n*k*(m+8)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
В добавок к этому при добавлении/удалении транзакции к кластеру производится пересчет его характеристик: &amp;lt;math&amp;gt;m+2&amp;lt;/math&amp;gt; операции.&lt;br /&gt;
&lt;br /&gt;
Из того можно сделать вывод, что оценка сложность алгоритма равна &amp;lt;math&amp;gt;O(n*k*m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
&lt;br /&gt;
[[File:InitDef.PNG||700px]]&lt;br /&gt;
&lt;br /&gt;
Этап итераций отличается только тем, что на нем дополнительно считается функция &#039;&#039;&#039;DeltaRemove&#039;&#039;&#039; вычисления стоимости удаления транзакции с кластера. На этапе итерации функции DeltaAdd/DeltaRemove могут считать параллельно для каждой транзакции.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Вычисление стоимости добавления/удаления транзакции, которые выполняются функциями DeltaAdd/DeltaRemove, происходит независимо для всех &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; кластеров. Поэтому все вычисления можно производить параллельно. Таким образом сложность алгоритма с &amp;lt;math&amp;gt;O(n*k*m)&amp;lt;/math&amp;gt; понижается до &amp;lt;math&amp;gt;O(n*m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; транзакций длины &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; и коэффициент отталкивания &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
метки классов для каждой транзакции в соответствии с проведенной кластеризацией(числовая последовательность длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной сложности алгоритма определяется количеством кластеров: &amp;lt;math&amp;gt;\dfrac{O(n*k*m)}{O(n*m)} = k&amp;lt;/math&amp;gt;&lt;br /&gt;
* [[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]] алгоритма равна &amp;lt;math&amp;gt;\dfrac{nk(m+8) + m + 2}{nm + n + 1} \cong k&amp;lt;/math&amp;gt;&lt;br /&gt;
* Алгоритм не является [[глоссарий#Устойчивость|&#039;&#039;устойчивым&#039;&#039;]], так как результат работы зависит от порядка чтения транзакций и от текущего набора транзакций в кластере.&lt;br /&gt;
* Выполняется свойство сбалансированности операций между параллельными ветвями алгоритма, так как для каждой транзакции выполняются функции DeltaAdd/DeltaRemove, считающие стоимость добавления/удаления транзакции.&lt;br /&gt;
* Свойство [[глоссарий#Детерминированность|&#039;&#039;детерминированности алгоритмов&#039;&#039;]] не выполняется, так как результат алгоритма зависит от порядка прохождения транзакций. Но если рассматривать транзакции как нумерованный список, то результат будет определен однозначно от запуска к запуску. Однако существует расширение алгоритма, обеспечивающее свойство детерминированности. &amp;lt;ref&amp;gt;Li, Y., Le, J., Wang, M. Improving CLOPE’s Profit Value and Stability with an Optimized Agglomerative Approach. Algorithms 2015, 8, 380-394.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
* Так как алгоритм предназначен для кластеризации категориальных данных, то он практически неприменим для числовой кластеризации.&lt;br /&gt;
* Быстро работает даже для большого количества данных, обеспечивая при этом хорошее качество кластеризации&lt;br /&gt;
* Имеет простую реализацию&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
Проверка масштабируемости проводилась на суперкомпьютере &amp;quot;Ломоносов&amp;quot; с числом процессоров 1, 8, 16, 32 и 64. Результаты проверки на графике ниже.&lt;br /&gt;
[[file:Graf_lom.png||700px]]&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
* http://weka.sourceforge.net/doc.stable/weka/clusterers/CLOPE.html - реализация в open source библиотеке для анализа данных WEKA(Waikato Environment for Knowledge Analysis) на языке Java&lt;br /&gt;
Также существуют пользовательские реализации алгоритма:&lt;br /&gt;
* https://github.com/infozor/php_mysql_clustering_clope - реализация алгоритма на PHP&lt;br /&gt;
* https://github.com/Tolsi/scala-clope - реализация алгоритма Scala&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:%D0%9F%D0%B0%D0%B2%D0%B5%D0%BB/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BA%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D0%B9%D0%BD%D1%8B%D1%85_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85_CLOPE&amp;diff=21591</id>
		<title>Участник:Павел/Алгоритм кластеризации категорийных данных CLOPE</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9F%D0%B0%D0%B2%D0%B5%D0%BB/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BA%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D0%B9%D0%BD%D1%8B%D1%85_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85_CLOPE&amp;diff=21591"/>
		<updated>2017-01-19T14:04: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;
Алгоритм CLOPE (Clustering with sLOPE&amp;lt;ref&amp;gt;Yang, Y., Guan, H., You. J. CLOPE: A fast and Effective Clustering Algorithm for Transactional Data In Proc. of SIGKDD’02, July 23-26, 2002, Edmonton, Alberta, Canada.&amp;lt;/ref&amp;gt;) неирархический метод кластеризации, предназначенный для кластеризации огромных наборов категорийных данных. К достоинствам алгоритма относятся высокие масштабируемость и скорость работы и качество кластеризации, что достигается использованием глобального критерия оптимизации на основе максимизации градиента высоты гистограммы кластера. Отличается простотой программной реализации. &lt;br /&gt;
&lt;br /&gt;
Во время работы алгоритм хранит в памяти небольшое количество информации по каждому кластеру и требует минимальное число сканирований набора данных. CLOPE автоматически подбирает количество кластеров, причем это регулируется одним единственным параметром - коэффициентом отталкивания &amp;lt;math&amp;gt; r &amp;lt;/math&amp;gt;. При этом он обеспечивает более высокую производительность и лучшее качество кластеризации в сравнении с многими иерархическими алгоритмами.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
Пусть имеется база транзакций &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, состоящая из множества транзакций &amp;lt;math&amp;gt;\{t_1,t_2,...,t_n\}&amp;lt;/math&amp;gt;. Каждая транзакция есть набор объектов &amp;lt;math&amp;gt;\{i_1,...,i_m\}&amp;lt;/math&amp;gt;. Множество кластеров &amp;lt;math&amp;gt;\{C_1,...,C_k\}&amp;lt;/math&amp;gt; есть разбиение множества &amp;lt;math&amp;gt;\{t_1,...,t_n\}&amp;lt;/math&amp;gt;, такое, что &amp;lt;math&amp;gt;C_1 \cup \dots \cup C_k=\{t_1,...,t_n\}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_i \ne \empty&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_i \cap C_j = \empty &amp;lt;/math&amp;gt;, для &amp;lt;math&amp;gt;i \ge 1, k \ge j&amp;lt;/math&amp;gt;. Каждый элемент &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; называется кластером, а &amp;lt;math&amp;gt;n, m, k&amp;lt;/math&amp;gt; – количество транзакций, количество объектов в базе транзакций и число кластеров соответственно.&lt;br /&gt;
&lt;br /&gt;
Каждый кластер &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; имеет следующие характеристики:&lt;br /&gt;
&amp;lt;math&amp;gt;D(C)&amp;lt;/math&amp;gt; – множество уникальных объектов;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;Occ(i,C)&amp;lt;/math&amp;gt; – количество вхождений (частота) объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; в кластер &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;S(C)= \sum_{i \in D(C)} Occ(i,C)= \sum_{t_i \in C}  \mid t_i  \mid , &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;W(C)=  \mid D(C) \mid ,H(C)=S(C)/W(C) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Функция стоимости:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; Profit(C) = \frac{\sum^{k}_{i=1} G(C_i) \times \mid C_i \mid} {\sum^{k}_{i=1} \mid C_i \mid } = \frac{\sum^{k}_{i=1} \frac{S(C_i)}{W(C_i)^r} \times \mid C_i \mid} {\sum^{k}_{i=1} \mid C_i \mid }  &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;\mid C_i \mid&amp;lt;/math&amp;gt;  количество объектов в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом кластере, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; – количество кластеров, &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; – коэффициент отталкивания &amp;lt;math&amp;gt;(0 &amp;lt; r \le 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С помощью параметра &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; регулируется уровень сходства транзакций внутри кластера, и, как&lt;br /&gt;
следствие, финальное количество кластеров. Этот коэффициент подбирается пользователем. Чем больше &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt;, тем ниже уровень сходства и тем больше кластеров будет сгенерировано.&lt;br /&gt;
&lt;br /&gt;
Постановка задачи кластеризации алгоритмом CLOPE выглядит следующим образом: &lt;br /&gt;
&lt;br /&gt;
для заданных &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; найти разбиение &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; такое, что: &lt;br /&gt;
&amp;lt;math&amp;gt;Profit(C) \longrightarrow max &amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит в вычислении на каждой итерации стоимости добавления и удаления транзакции из кластера: &lt;br /&gt;
&lt;br /&gt;
*вычисление нового размера кластера &amp;lt;math&amp;gt;S_{new}(C_i)=S(C_i) \pm \mid(t_n)\mid &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\mid(t_n)\mid&amp;lt;/math&amp;gt; - длина транзакции&lt;br /&gt;
&lt;br /&gt;
*вычисление новой ширины кластера &amp;lt;math&amp;gt;W_{new}(C_i)=\mid D(C_i \cup t_n)|&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*вычисление стоимости &amp;lt;math&amp;gt;\frac{S_{new}(C_i)(\mid C_i \mid \pm 1)}{W_{new}(C_i)^r} - \frac{S(C_i) \mid C_i \mid }{W(C_i)^r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм состоит из следующих этапов:&lt;br /&gt;
&lt;br /&gt;
1. &#039;&#039;&#039;Инициализация&#039;&#039;&#039;. На этом этапе происходит первый проход по таблице с транзакциями для построения начального разбиения, для каждой транзакции определяется кластер исходя из максимизации стоимости.&lt;br /&gt;
&lt;br /&gt;
2. &#039;&#039;&#039;Итерация&#039;&#039;&#039;. На данном этапе для каждой транзакции проводится попытка перемещения в другой кластер для максимизации функции стоимости.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Первая часть алгоритма - инициализация: для каждой транзакции вычисляется кластер, к которому она будет отнесена исходя из максимизации функции стоимости. Для этого вычисляется вспомогательная функция DeltaAdd, которая считает стоимость добавления транзакции к одному из существующих кластеров, либо к пустому. В итоге транзакция помещается в кластер, для которого цена добавления максимальна.&lt;br /&gt;
&lt;br /&gt;
Вторая часть алгоритма - уточняющие итерации: здесь происходит попытка улучшить вычисленные на первом этапе кластеры. В каждой итерации происходит перебор всех транзакций, и для каждой транзакции вычисляется цена удаления ее из текущего кластера и цена добавления в другой кластер. Суммарная стоимость перемещения будет являться суммой стоимостей удаления и добавления. Если максимальная стоимость перемещения данной транзакции в какой-либо больше нуля, то она перемещается в этот кластер. &lt;br /&gt;
&lt;br /&gt;
Вычисления происходят до тех пор, пока за итерацию происходит хотя бы одно перемещение транзакции. Если за итерацию не было произведено ни одного перемещения, то текущее состояние кластеров является устойчивым и оптимальным. &amp;lt;ref&amp;gt;Павлин Н. Кластеризация категорийных данных: масштабируемый алгоритм CLOPE, https://basegroup.ru/community/articles/clope&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Схема реализации на псевдокоде:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Входные параметры:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - транзакции&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; - коэффициент отталкивания&lt;br /&gt;
&lt;br /&gt;
Выходной параметр:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; кластеры, в начале алгоритма - пустое множество&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация:&#039;&#039;&#039;&lt;br /&gt;
    &#039;&#039;&#039;for&#039;&#039;&#039; t_i in t:&lt;br /&gt;
    max = 0&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; C_j in C:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; DeltaAdd(C_j,t_i,r) &amp;gt; max:&lt;br /&gt;
                max = DeltaAdd(C_j,t_i,r)&lt;br /&gt;
                C_best = C_j&lt;br /&gt;
    &#039;&#039;&#039;put&#039;&#039;&#039; t_i in C_best&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Итерации:&#039;&#039;&#039;&lt;br /&gt;
    move = True&lt;br /&gt;
    &#039;&#039;&#039;while&#039;&#039;&#039; move == True:&lt;br /&gt;
    move = False&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; t_i in t:&lt;br /&gt;
            max = 0&lt;br /&gt;
            C_now = t_i.cluster&lt;br /&gt;
            removeCost = DeltaRemove(C_now,t_i,r)&lt;br /&gt;
            &#039;&#039;&#039;for&#039;&#039;&#039; C_j in C:&lt;br /&gt;
                &#039;&#039;&#039;if&#039;&#039;&#039; DeltaAdd(C_j,t_i,r) + removeCost &amp;gt; max:&lt;br /&gt;
                    max = DeltaAdd(C_j,t_i,r) + removeCost&lt;br /&gt;
                    C_best = C_j&lt;br /&gt;
        if max &amp;gt; 0&lt;br /&gt;
            &#039;&#039;&#039;del&#039;&#039;&#039; t_i from C_now&lt;br /&gt;
            &#039;&#039;&#039;put&#039;&#039;&#039; t_i in C_best&lt;br /&gt;
            move = True&lt;br /&gt;
&lt;br /&gt;
Вспомогательная функция &#039;&#039;&#039;DeltaAdd&#039;&#039;&#039;:&lt;br /&gt;
    &#039;&#039;&#039;function&#039;&#039;&#039; DeltaAdd(C,t,r)&lt;br /&gt;
        S_new=C.size + t.itemCount&lt;br /&gt;
        W_new=C.wigth&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; item in t_i:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; C_j.occ(item) = 0&lt;br /&gt;
                &#039;&#039;W_new = W_new + 1&lt;br /&gt;
        &#039;&#039;&#039;return&#039;&#039;&#039; S_new * (C.count+1) / (W_new ^ r) - (C.size * C.count) / (C.wigth ^ r)&lt;br /&gt;
&lt;br /&gt;
Вспомогательная функция &#039;&#039;&#039;DeltaRemove&#039;&#039;&#039;:&lt;br /&gt;
    &#039;&#039;&#039;function&#039;&#039;&#039; DeltaRemove(C,t,r)&lt;br /&gt;
        S_new=C.size - t.itemCount&lt;br /&gt;
        W_new=C.wigth&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; item in t:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; C_j.occ(item) = 1&lt;br /&gt;
                &#039;&#039;W_new = W_new - 1&lt;br /&gt;
        &#039;&#039;&#039;return&#039;&#039;&#039; S_new * (C.count-1) / (W_new ^ r) - (C.size * C.count) / (C.wigth ^ r)&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
В соответствии с ранее введенным обозначением &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - количество транзакций, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина транзакции(максимальная), &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество кластеров.&lt;br /&gt;
&lt;br /&gt;
Основные вычисления восполняются в функции DeltaAdd/DeltaRemove: производится 1 сложение, не более &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; сложений/вычитаний, 2 умножения, 2 деления, 2 возведения в степень и 1 сложение - итого &amp;lt;math&amp;gt;m + 8&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;k&amp;lt;/math&amp;gt; штук). Итого выполняется &amp;lt;math&amp;gt;n*k*(m+8)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
В добавок к этому при добавлении/удалении транзакции к кластеру производится пересчет его характеристик: &amp;lt;math&amp;gt;m+2&amp;lt;/math&amp;gt; операции.&lt;br /&gt;
&lt;br /&gt;
Из того можно сделать вывод, что оценка сложность алгоритма равна &amp;lt;math&amp;gt;O(n*k*m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
&lt;br /&gt;
На рисунке ниже представлена схема этапа инициализации на примере входной транзакции &amp;lt;math&amp;gt;T&amp;lt;/math&amp;gt; и четырех кластеров &amp;lt;math&amp;gt;Cl 1&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;Cl 2&amp;lt;/math&amp;gt;, &amp;lt;math&amp;gt;Cl 3&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;Cl 1&amp;lt;/math&amp;gt;. Объект &#039;&#039;&#039;DeltaAdd&#039;&#039;&#039; соответствует выполнению соответствующей функции для вычисления цены добавления транзакции на кластер. После выполнения всех &#039;&#039;&#039;DeltaAdd&#039;&#039;&#039; для одной транзакции выполняется определение максимального значения функции и выбор кластера, на который будет помещена транзакция. На этапе инициализации при обработке каждой транзакции количество кластеров может как увеличиться, так и остаться неизменным.&lt;br /&gt;
[[File:InitDef.PNG||700px]]&lt;br /&gt;
Этап итераций отличается только тем, что на нем дополнительно считается функция &#039;&#039;&#039;DeltaRemove&#039;&#039;&#039; вычисления стоимости удаления транзакции с кластера. На этапе итерации функции DeltaAdd/DeltaRemove могут считать параллельно для каждой транзакции.&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Вычисление стоимости добавления/удаления транзакции, которые выполняются функциями DeltaAdd/DeltaRemove, происходит независимо для всех &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; кластеров. Поэтому все вычисления можно производить параллельно. Таким образом сложность алгоритма с &amp;lt;math&amp;gt;O(n*k*m)&amp;lt;/math&amp;gt; понижается до &amp;lt;math&amp;gt;O(n*m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; транзакций длины &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; и коэффициент отталкивания &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
метки классов для каждой транзакции в соответствии с проведенной кластеризацией(числовая последовательность длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной сложности алгоритма определяется количеством кластеров: &amp;lt;math&amp;gt;\dfrac{O(n*k*m)}{O(n*m)} = k&amp;lt;/math&amp;gt;&lt;br /&gt;
* [[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]] алгоритма равна &amp;lt;math&amp;gt;\dfrac{nk(m+8) + m + 2}{nm + n + 1} \cong k&amp;lt;/math&amp;gt;&lt;br /&gt;
* Алгоритм не является [[глоссарий#Устойчивость|&#039;&#039;устойчивым&#039;&#039;]], так как результат работы зависит от порядка чтения транзакций и от текущего набора транзакций в кластере.&lt;br /&gt;
* Выполняется свойство сбалансированности операций между параллельными ветвями алгоритма, так как для каждой транзакции выполняются функции DeltaAdd/DeltaRemove, считающие стоимость добавления/удаления транзакции.&lt;br /&gt;
* Свойство [[глоссарий#Детерминированность|&#039;&#039;детерминированности алгоритмов&#039;&#039;]] не выполняется, так как результат алгоритма зависит от порядка прохождения транзакций. Но если рассматривать транзакции как нумерованный список, то результат будет определен однозначно от запуска к запуску. Однако существует расширение алгоритма, обеспечивающее свойство детерминированности. &amp;lt;ref&amp;gt;Li, Y., Le, J., Wang, M. Improving CLOPE’s Profit Value and Stability with an Optimized Agglomerative Approach. Algorithms 2015, 8, 380-394.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
* Так как алгоритм предназначен для кластеризации категориальных данных, то он практически неприменим для числовой кластеризации.&lt;br /&gt;
* Быстро работает даже для большого количества данных, обеспечивая при этом хорошее качество кластеризации&lt;br /&gt;
* Имеет простую реализацию&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
Проверка масштабируемости проводилась на суперкомпьютере &amp;quot;Ломоносов&amp;quot; с числом процессоров 1, 8, 16, 32 и 64. Результаты проверки на графике ниже.&lt;br /&gt;
[[file:Graf_lom.png||700px]]&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
* http://weka.sourceforge.net/doc.stable/weka/clusterers/CLOPE.html - реализация в open source библиотеке для анализа данных WEKA(Waikato Environment for Knowledge Analysis) на языке Java&lt;br /&gt;
Также существуют пользовательские реализации алгоритма:&lt;br /&gt;
* https://github.com/infozor/php_mysql_clustering_clope - реализация алгоритма на PHP&lt;br /&gt;
* https://github.com/Tolsi/scala-clope - реализация алгоритма Scala&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:%D0%9F%D0%B0%D0%B2%D0%B5%D0%BB/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BA%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D0%B9%D0%BD%D1%8B%D1%85_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85_CLOPE&amp;diff=21545</id>
		<title>Участник:Павел/Алгоритм кластеризации категорийных данных CLOPE</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9F%D0%B0%D0%B2%D0%B5%D0%BB/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BA%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D0%B9%D0%BD%D1%8B%D1%85_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85_CLOPE&amp;diff=21545"/>
		<updated>2017-01-17T12:28:13Z</updated>

		<summary type="html">&lt;p&gt;Павел: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
Автор описания: [[Участник:Павел|П.М.Бронников]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
Алгоритм CLOPE (Clustering with sLOPE&amp;lt;ref&amp;gt;Yang, Y., Guan, H., You. J. CLOPE: A fast and Effective Clustering Algorithm for Transactional Data In Proc. of SIGKDD’02, July 23-26, 2002, Edmonton, Alberta, Canada.&amp;lt;/ref&amp;gt;) неирархический метод кластеризации, предназначенный для кластеризации огромных наборов категорийных данных. К достоинствам алгоритма относятся высокие масштабируемость и скорость работы и качество кластеризации, что достигается использованием глобального критерия оптимизации на основе максимизации градиента высоты гистограммы кластера. Отличается простотой программной реализации. &lt;br /&gt;
&lt;br /&gt;
Во время работы алгоритм хранит в памяти небольшое количество информации по каждому кластеру и требует минимальное число сканирований набора данных. CLOPE автоматически подбирает количество кластеров, причем это регулируется одним единственным параметром - коэффициентом отталкивания &amp;lt;math&amp;gt; r &amp;lt;/math&amp;gt;. При этом он обеспечивает более высокую производительность и лучшее качество кластеризации в сравнении с многими иерархическими алгоритмами.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
Пусть имеется база транзакций &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, состоящая из множества транзакций &amp;lt;math&amp;gt;\{t_1,t_2,...,t_n\}&amp;lt;/math&amp;gt;. Каждая транзакция есть набор объектов &amp;lt;math&amp;gt;\{i_1,...,i_m\}&amp;lt;/math&amp;gt;. Множество кластеров &amp;lt;math&amp;gt;\{C_1,...,C_k\}&amp;lt;/math&amp;gt; есть разбиение множества &amp;lt;math&amp;gt;\{t_1,...,t_n\}&amp;lt;/math&amp;gt;, такое, что &amp;lt;math&amp;gt;C_1 \cup \dots \cup C_k=\{t_1,...,t_n\}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_i \ne \empty&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_i \cap C_j = \empty &amp;lt;/math&amp;gt;, для &amp;lt;math&amp;gt;i \ge 1, k \ge j&amp;lt;/math&amp;gt;. Каждый элемент &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; называется кластером, а &amp;lt;math&amp;gt;n, m, k&amp;lt;/math&amp;gt; – количество транзакций, количество объектов в базе транзакций и число кластеров соответственно.&lt;br /&gt;
&lt;br /&gt;
Каждый кластер &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; имеет следующие характеристики:&lt;br /&gt;
&amp;lt;math&amp;gt;D(C)&amp;lt;/math&amp;gt; – множество уникальных объектов;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;Occ(i,C)&amp;lt;/math&amp;gt; – количество вхождений (частота) объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; в кластер &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;S(C)= \sum_{i \in D(C)} Occ(i,C)= \sum_{t_i \in C}  \mid t_i  \mid , &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;W(C)=  \mid D(C) \mid ,H(C)=S(C)/W(C) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Функция стоимости:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; Profit(C) = \frac{\sum^{k}_{i=1} G(C_i) \times \mid C_i \mid} {\sum^{k}_{i=1} \mid C_i \mid } = \frac{\sum^{k}_{i=1} \frac{S(C_i)}{W(C_i)^r} \times \mid C_i \mid} {\sum^{k}_{i=1} \mid C_i \mid }  &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;\mid C_i \mid&amp;lt;/math&amp;gt;  количество объектов в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом кластере, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; – количество кластеров, &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; – коэффициент отталкивания &amp;lt;math&amp;gt;(0 &amp;lt; r \le 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С помощью параметра &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; регулируется уровень сходства транзакций внутри кластера, и, как&lt;br /&gt;
следствие, финальное количество кластеров. Этот коэффициент подбирается пользователем. Чем больше &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt;, тем ниже уровень сходства и тем больше кластеров будет сгенерировано.&lt;br /&gt;
&lt;br /&gt;
Постановка задачи кластеризации алгоритмом CLOPE выглядит следующим образом: &lt;br /&gt;
&lt;br /&gt;
для заданных &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; найти разбиение &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; такое, что: &lt;br /&gt;
&amp;lt;math&amp;gt;Profit(C) \longrightarrow max &amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит в вычислении на каждой итерации стоимости добавления и удаления транзакции из кластера: &lt;br /&gt;
&lt;br /&gt;
*вычисление нового размера кластера &amp;lt;math&amp;gt;S_{new}(C_i)=S(C_i) \pm \mid(t_n)\mid &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\mid(t_n)\mid&amp;lt;/math&amp;gt; - длина транзакции&lt;br /&gt;
&lt;br /&gt;
*вычисление новой ширины кластера &amp;lt;math&amp;gt;W_{new}(C_i)=\mid D(C_i \cup t_n)|&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*вычисление стоимости &amp;lt;math&amp;gt;\frac{S_{new}(C_i)(\mid C_i \mid \pm 1)}{W_{new}(C_i)^r} - \frac{S(C_i) \mid C_i \mid }{W(C_i)^r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм состоит из следующих этапов:&lt;br /&gt;
&lt;br /&gt;
1. &#039;&#039;&#039;Инициализация&#039;&#039;&#039;. На этом этапе происходит первый проход по таблице с транзакциями для построения начального разбиения, для каждой транзакции определяется кластер исходя из максимизации стоимости.&lt;br /&gt;
&lt;br /&gt;
2. &#039;&#039;&#039;Итерация&#039;&#039;&#039;. На данном этапе для каждой транзакции проводится попытка перемещения в другой кластер для максимизации функции стоимости.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Первая часть алгоритма - инициализация: для каждой транзакции вычисляется кластер, к которому она будет отнесена исходя из максимизации функции стоимости. Для этого вычисляется вспомогательная функция DeltaAdd, которая считает стоимость добавления транзакции к одному из существующих кластеров, либо к пустому. В итоге транзакция помещается в кластер, для которого цена добавления максимальна.&lt;br /&gt;
&lt;br /&gt;
Вторая часть алгоритма - уточняющие итерации: здесь происходит попытка улучшить вычисленные на первом этапе кластеры. В каждой итерации происходит перебор всех транзакций, и для каждой транзакции вычисляется цена удаления ее из текущего кластера и цена добавления в другой кластер. Суммарная стоимость перемещения будет являться суммой стоимостей удаления и добавления. Если максимальная стоимость перемещения данной транзакции в какой-либо больше нуля, то она перемещается в этот кластер. &lt;br /&gt;
&lt;br /&gt;
Вычисления происходят до тех пор, пока за итерацию происходит хотя бы одно перемещение транзакции. Если за итерацию не было произведено ни одного перемещения, то текущее состояние кластеров является устойчивым и оптимальным. &amp;lt;ref&amp;gt;Павлин Н. Кластеризация категорийных данных: масштабируемый алгоритм CLOPE, https://basegroup.ru/community/articles/clope&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Схема реализации на псевдокоде:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Входные параметры:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - транзакции&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; - коэффициент отталкивания&lt;br /&gt;
&lt;br /&gt;
Выходной параметр:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; кластеры, в начале алгоритма - пустое множество&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация:&#039;&#039;&#039;&lt;br /&gt;
    &#039;&#039;&#039;for&#039;&#039;&#039; t_i in t:&lt;br /&gt;
    max = 0&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; C_j in C:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; DeltaAdd(C_j,t_i,r) &amp;gt; max:&lt;br /&gt;
                max = DeltaAdd(C_j,t_i,r)&lt;br /&gt;
                C_best = C_j&lt;br /&gt;
    &#039;&#039;&#039;put&#039;&#039;&#039; t_i in C_best&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Итерации:&#039;&#039;&#039;&lt;br /&gt;
    move = True&lt;br /&gt;
    &#039;&#039;&#039;while&#039;&#039;&#039; move == True:&lt;br /&gt;
    move = False&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; t_i in t:&lt;br /&gt;
            max = 0&lt;br /&gt;
            C_now = t_i.cluster&lt;br /&gt;
            removeCost = DeltaRemove(C_now,t_i,r)&lt;br /&gt;
            &#039;&#039;&#039;for&#039;&#039;&#039; C_j in C:&lt;br /&gt;
                &#039;&#039;&#039;if&#039;&#039;&#039; DeltaAdd(C_j,t_i,r) + removeCost &amp;gt; max:&lt;br /&gt;
                    max = DeltaAdd(C_j,t_i,r) + removeCost&lt;br /&gt;
                    C_best = C_j&lt;br /&gt;
        if max &amp;gt; 0&lt;br /&gt;
            &#039;&#039;&#039;del&#039;&#039;&#039; t_i from C_now&lt;br /&gt;
            &#039;&#039;&#039;put&#039;&#039;&#039; t_i in C_best&lt;br /&gt;
            move = True&lt;br /&gt;
&lt;br /&gt;
Вспомогательная функция &#039;&#039;&#039;DeltaAdd&#039;&#039;&#039;:&lt;br /&gt;
    &#039;&#039;&#039;function&#039;&#039;&#039; DeltaAdd(C,t,r)&lt;br /&gt;
        S_new=C.size + t.itemCount&lt;br /&gt;
        W_new=C.wigth&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; item in t_i:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; C_j.occ(item) = 0&lt;br /&gt;
                &#039;&#039;W_new = W_new + 1&lt;br /&gt;
        &#039;&#039;&#039;return&#039;&#039;&#039; S_new * (C.count+1) / (W_new ^ r) - (C.size * C.count) / (C.wigth ^ r)&lt;br /&gt;
&lt;br /&gt;
Вспомогательная функция &#039;&#039;&#039;DeltaRemove&#039;&#039;&#039;:&lt;br /&gt;
    &#039;&#039;&#039;function&#039;&#039;&#039; DeltaRemove(C,t,r)&lt;br /&gt;
        S_new=C.size - t.itemCount&lt;br /&gt;
        W_new=C.wigth&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; item in t:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; C_j.occ(item) = 1&lt;br /&gt;
                &#039;&#039;W_new = W_new - 1&lt;br /&gt;
        &#039;&#039;&#039;return&#039;&#039;&#039; S_new * (C.count-1) / (W_new ^ r) - (C.size * C.count) / (C.wigth ^ r)&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
В соответствии с ранее введенным обозначением &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - количество транзакций, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина транзакции(максимальная), &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество кластеров.&lt;br /&gt;
&lt;br /&gt;
Основные вычисления восполняются в функции DeltaAdd/DeltaRemove: производится 1 сложение, не более &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; сложений/вычитаний, 2 умножения, 2 деления, 2 возведения в степень и 1 сложение - итого &amp;lt;math&amp;gt;m + 8&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;k&amp;lt;/math&amp;gt; штук). Итого выполняется &amp;lt;math&amp;gt;n*k*(m+8)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
В добавок к этому при добавлении/удалении транзакции к кластеру производится пересчет его характеристик: &amp;lt;math&amp;gt;m+2&amp;lt;/math&amp;gt; операции.&lt;br /&gt;
&lt;br /&gt;
Из того можно сделать вывод, что оценка сложность алгоритма равна &amp;lt;math&amp;gt;O(n*k*m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
[[File:1_inic.jpg|300px|thumb|left|Инициализация]]&lt;br /&gt;
[[File:2_iter.jpg|300px|thumb|right|Итерации]]&lt;br /&gt;
На этапе инициализации при обработке каждой транзакции количество кластеров может как увеличиться, так и остаться неизменным. На этапе итерации функции DeltaAdd/DeltaRemove могут считать параллельно для каждой транзакции.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Вычисление стоимости добавления/удаления транзакции, которые выполняются функциями DeltaAdd/DeltaRemove, происходит независимо для всех &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; кластеров. Поэтому все вычисления можно производить параллельно. Таким образом сложность алгоритма с &amp;lt;math&amp;gt;O(n*k*m)&amp;lt;/math&amp;gt; понижается до &amp;lt;math&amp;gt;O(n*m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; транзакций длины &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; и коэффициент отталкивания &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
метки классов для каждой транзакции в соответствии с проведенной кластеризацией(числовая последовательность длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной сложности алгоритма определяется количеством кластеров: &amp;lt;math&amp;gt;\dfrac{O(n*k*m)}{O(n*m)} = k&amp;lt;/math&amp;gt;&lt;br /&gt;
* [[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]] алгоритма равна &amp;lt;math&amp;gt;\dfrac{nk(m+8) + m + 2}{nm + n + 1} \cong k&amp;lt;/math&amp;gt;&lt;br /&gt;
* Алгоритм не является [[глоссарий#Устойчивость|&#039;&#039;устойчивым&#039;&#039;]], так как результат работы зависит от порядка чтения транзакций и от текущего набора транзакций в кластере.&lt;br /&gt;
* Выполняется свойство сбалансированности операций между параллельными ветвями алгоритма, так как для каждой транзакции выполняются функции DeltaAdd/DeltaRemove, считающие стоимость добавления/удаления транзакции.&lt;br /&gt;
* Свойство [[глоссарий#Детерминированность|&#039;&#039;детерминированности алгоритмов&#039;&#039;]] не выполняется, так как результат алгоритма зависит от порядка прохождения транзакций. Но если рассматривать транзакции как нумерованный список, то результат будет определен однозначно от запуска к запуску. Однако существует расширение алгоритма, обеспечивающее свойство детерминированности. &amp;lt;ref&amp;gt;Li, Y., Le, J., Wang, M. Improving CLOPE’s Profit Value and Stability with an Optimized Agglomerative Approach. Algorithms 2015, 8, 380-394.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
* Так как алгоритм предназначен для кластеризации категориальных данных, то он практически неприменим для числовой кластеризации.&lt;br /&gt;
* Быстро работает даже для большого количества данных, обеспечивая при этом хорошее качество кластеризации&lt;br /&gt;
* Имеет простую реализацию&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
Проверка масштабируемости проводилась на суперкомпьютере &amp;quot;Ломоносов&amp;quot; с числом процессоров 1, 8, 16, 32 и 64. Результаты проверки на графике ниже.&lt;br /&gt;
[[file:Graf_lom.png||700px]]&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
* http://weka.sourceforge.net/doc.stable/weka/clusterers/CLOPE.html - реализация в open source библиотеке для анализа данных WEKA(Waikato Environment for Knowledge Analysis) на языке Java&lt;br /&gt;
Также существуют пользовательские реализации алгоритма:&lt;br /&gt;
* https://github.com/infozor/php_mysql_clustering_clope - реализация алгоритма на PHP&lt;br /&gt;
* https://github.com/Tolsi/scala-clope - реализация алгоритма Scala&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:%D0%9F%D0%B0%D0%B2%D0%B5%D0%BB/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BA%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D0%B9%D0%BD%D1%8B%D1%85_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85_CLOPE&amp;diff=21544</id>
		<title>Участник:Павел/Алгоритм кластеризации категорийных данных CLOPE</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9F%D0%B0%D0%B2%D0%B5%D0%BB/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BA%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D0%B9%D0%BD%D1%8B%D1%85_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85_CLOPE&amp;diff=21544"/>
		<updated>2017-01-17T12:25:27Z</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;
Алгоритм CLOPE (Clustering with sLOPE&amp;lt;ref&amp;gt;Yang, Y., Guan, H., You. J. CLOPE: A fast and Effective Clustering Algorithm for Transactional Data In Proc. of SIGKDD’02, July 23-26, 2002, Edmonton, Alberta, Canada.&amp;lt;/ref&amp;gt;) неирархический метод кластеризации, предназначенный для кластеризации огромных наборов категорийных данных. К достоинствам алгоритма относятся высокие масштабируемость и скорость работы и качество кластеризации, что достигается использованием глобального критерия оптимизации на основе максимизации градиента высоты гистограммы кластера. Отличается простотой программной реализации. &lt;br /&gt;
&lt;br /&gt;
Во время работы алгоритм хранит в памяти небольшое количество информации по каждому кластеру и требует минимальное число сканирований набора данных. CLOPE автоматически подбирает количество кластеров, причем это регулируется одним единственным параметром - коэффициентом отталкивания &amp;lt;math&amp;gt; r &amp;lt;/math&amp;gt;. При этом он обеспечивает более высокую производительность и лучшее качество кластеризации в сравнении с многими иерархическими алгоритмами.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
Пусть имеется база транзакций &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, состоящая из множества транзакций &amp;lt;math&amp;gt;\{t_1,t_2,...,t_n\}&amp;lt;/math&amp;gt;. Каждая транзакция есть набор объектов &amp;lt;math&amp;gt;\{i_1,...,i_m\}&amp;lt;/math&amp;gt;. Множество кластеров &amp;lt;math&amp;gt;\{C_1,...,C_k\}&amp;lt;/math&amp;gt; есть разбиение множества &amp;lt;math&amp;gt;\{t_1,...,t_n\}&amp;lt;/math&amp;gt;, такое, что &amp;lt;math&amp;gt;C_1 \cup \dots \cup C_k=\{t_1,...,t_n\}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_i \ne \empty&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_i \cap C_j = \empty &amp;lt;/math&amp;gt;, для &amp;lt;math&amp;gt;i \ge 1, k \ge j&amp;lt;/math&amp;gt;. Каждый элемент &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; называется кластером, а &amp;lt;math&amp;gt;n, m, k&amp;lt;/math&amp;gt; – количество транзакций, количество объектов в базе транзакций и число кластеров соответственно.&lt;br /&gt;
&lt;br /&gt;
Каждый кластер &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; имеет следующие характеристики:&lt;br /&gt;
&amp;lt;math&amp;gt;D(C)&amp;lt;/math&amp;gt; – множество уникальных объектов;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;Occ(i,C)&amp;lt;/math&amp;gt; – количество вхождений (частота) объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; в кластер &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;S(C)= \sum_{i \in D(C)} Occ(i,C)= \sum_{t_i \in C}  \mid t_i  \mid , &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;W(C)=  \mid D(C) \mid ,H(C)=S(C)/W(C) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Функция стоимости:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; Profit(C) = \frac{\sum^{k}_{i=1} G(C_i) \times \mid C_i \mid} {\sum^{k}_{i=1} \mid C_i \mid } = \frac{\sum^{k}_{i=1} \frac{S(C_i)}{W(C_i)^r} \times \mid C_i \mid} {\sum^{k}_{i=1} \mid C_i \mid }  &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;\mid C_i \mid&amp;lt;/math&amp;gt;  количество объектов в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом кластере, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; – количество кластеров, &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; – коэффициент отталкивания &amp;lt;math&amp;gt;(0 &amp;lt; r \le 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С помощью параметра &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; регулируется уровень сходства транзакций внутри кластера, и, как&lt;br /&gt;
следствие, финальное количество кластеров. Этот коэффициент подбирается пользователем. Чем больше &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt;, тем ниже уровень сходства и тем больше кластеров будет сгенерировано.&lt;br /&gt;
&lt;br /&gt;
Постановка задачи кластеризации алгоритмом CLOPE выглядит следующим образом: &lt;br /&gt;
&lt;br /&gt;
для заданных &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; найти разбиение &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; такое, что: &lt;br /&gt;
&amp;lt;math&amp;gt;Profit(C) \longrightarrow max &amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит в вычислении на каждой итерации стоимости добавления и удаления транзакции из кластера: &lt;br /&gt;
&lt;br /&gt;
*вычисление нового размера кластера &amp;lt;math&amp;gt;S_{new}(C_i)=S(C_i) \pm \mid(t_n)\mid &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\mid(t_n)\mid&amp;lt;/math&amp;gt; - длина транзакции&lt;br /&gt;
&lt;br /&gt;
*вычисление новой ширины кластера &amp;lt;math&amp;gt;W_{new}(C_i)=\mid D(C_i \cup t_n)|&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*вычисление стоимости &amp;lt;math&amp;gt;\frac{S_{new}(C_i)(\mid C_i \mid \pm 1)}{W_{new}(C_i)^r} - \frac{S(C_i) \mid C_i \mid }{W(C_i)^r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм состоит из следующих этапов:&lt;br /&gt;
&lt;br /&gt;
1. &#039;&#039;&#039;Инициализация&#039;&#039;&#039;. На этом этапе происходит первый проход по таблице с транзакциями для построения начального разбиения, для каждой транзакции определяется кластер исходя из максимизации стоимости.&lt;br /&gt;
&lt;br /&gt;
2. &#039;&#039;&#039;Итерация&#039;&#039;&#039;. На данном этапе для каждой транзакции проводится попытка перемещения в другой кластер для максимизации функции стоимости.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Первая часть алгоритма - инициализация: для каждой транзакции вычисляется кластер, к которому она будет отнесена исходя из максимизации функции стоимости. Для этого вычисляется вспомогательная функция DeltaAdd, которая считает стоимость добавления транзакции к одному из существующих кластеров, либо к пустому. В итоге транзакция помещается в кластер, для которого цена добавления максимальна.&lt;br /&gt;
&lt;br /&gt;
Вторая часть алгоритма - уточняющие итерации: здесь происходит попытка улучшить вычисленные на первом этапе кластеры. В каждой итерации происходит перебор всех транзакций, и для каждой транзакции вычисляется цена удаления ее из текущего кластера и цена добавления в другой кластер. Суммарная стоимость перемещения будет являться суммой стоимостей удаления и добавления. Если максимальная стоимость перемещения данной транзакции в какой-либо больше нуля, то она перемещается в этот кластер. &lt;br /&gt;
&lt;br /&gt;
Вычисления происходят до тех пор, пока за итерацию происходит хотя бы одно перемещение транзакции. Если за итерацию не было произведено ни одного перемещения, то текущее состояние кластеров является устойчивым и оптимальным. &amp;lt;ref&amp;gt;Павлин Н. Кластеризация категорийных данных: масштабируемый алгоритм CLOPE, https://basegroup.ru/community/articles/clope&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Схема реализации на псевдокоде:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Входные параметры:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - транзакции&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; - коэффициент отталкивания&lt;br /&gt;
&lt;br /&gt;
Выходной параметр:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; кластеры, в начале алгоритма - пустое множество&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация:&#039;&#039;&#039;&lt;br /&gt;
    &#039;&#039;&#039;for&#039;&#039;&#039; t_i in t:&lt;br /&gt;
    max = 0&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; C_j in C:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; DeltaAdd(C_j,t_i,r) &amp;gt; max:&lt;br /&gt;
                max = DeltaAdd(C_j,t_i,r)&lt;br /&gt;
                C_best = C_j&lt;br /&gt;
    &#039;&#039;&#039;put&#039;&#039;&#039; t_i in C_best&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Итерации:&#039;&#039;&#039;&lt;br /&gt;
    move = True&lt;br /&gt;
    &#039;&#039;&#039;while&#039;&#039;&#039; move == True:&lt;br /&gt;
    move = False&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; t_i in t:&lt;br /&gt;
            max = 0&lt;br /&gt;
            C_now = t_i.cluster&lt;br /&gt;
            removeCost = DeltaRemove(C_now,t_i,r)&lt;br /&gt;
            &#039;&#039;&#039;for&#039;&#039;&#039; C_j in C:&lt;br /&gt;
                &#039;&#039;&#039;if&#039;&#039;&#039; DeltaAdd(C_j,t_i,r) + removeCost &amp;gt; max:&lt;br /&gt;
                    max = DeltaAdd(C_j,t_i,r) + removeCost&lt;br /&gt;
                    C_best = C_j&lt;br /&gt;
        if max &amp;gt; 0&lt;br /&gt;
            &#039;&#039;&#039;del&#039;&#039;&#039; t_i from C_now&lt;br /&gt;
            &#039;&#039;&#039;put&#039;&#039;&#039; t_i in C_best&lt;br /&gt;
            move = True&lt;br /&gt;
&lt;br /&gt;
Вспомогательная функция &#039;&#039;&#039;DeltaAdd&#039;&#039;&#039;:&lt;br /&gt;
    &#039;&#039;&#039;function&#039;&#039;&#039; DeltaAdd(C,t,r)&lt;br /&gt;
        S_new=C.size + t.itemCount&lt;br /&gt;
        W_new=C.wigth&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; item in t_i:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; C_j.occ(item) = 0&lt;br /&gt;
                &#039;&#039;W_new = W_new + 1&lt;br /&gt;
        &#039;&#039;&#039;return&#039;&#039;&#039; S_new * (C.count+1) / (W_new ^ r) - (C.size * C.count) / (C.wigth ^ r)&lt;br /&gt;
&lt;br /&gt;
Вспомогательная функция &#039;&#039;&#039;DeltaRemove&#039;&#039;&#039;:&lt;br /&gt;
    &#039;&#039;&#039;function&#039;&#039;&#039; DeltaRemove(C,t,r)&lt;br /&gt;
        S_new=C.size - t.itemCount&lt;br /&gt;
        W_new=C.wigth&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; item in t:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; C_j.occ(item) = 1&lt;br /&gt;
                &#039;&#039;W_new = W_new - 1&lt;br /&gt;
        &#039;&#039;&#039;return&#039;&#039;&#039; S_new * (C.count-1) / (W_new ^ r) - (C.size * C.count) / (C.wigth ^ r)&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
В соответствии с ранее введенным обозначением &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - количество транзакций, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина транзакции(максимальная), &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество кластеров.&lt;br /&gt;
&lt;br /&gt;
Основные вычисления восполняются в функции DeltaAdd/DeltaRemove: производится 1 сложение, не более &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; сложений/вычитаний, 2 умножения, 2 деления, 2 возведения в степень и 1 сложение - итого &amp;lt;math&amp;gt;m + 8&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;k&amp;lt;/math&amp;gt; штук). Итого выполняется &amp;lt;math&amp;gt;n*k*(m+8)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
В добавок к этому при добавлении/удалении транзакции к кластеру производится пересчет его характеристик: &amp;lt;math&amp;gt;m+2&amp;lt;/math&amp;gt; операции.&lt;br /&gt;
&lt;br /&gt;
Из того можно сделать вывод, что оценка сложность алгоритма равна &amp;lt;math&amp;gt;O(n*k*m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
[[File:1_inic.jpg|300px|thumb|left|Инициализация]]&lt;br /&gt;
[[File:2_iter.jpg|300px|thumb|right|Итерации]]&lt;br /&gt;
На этапе инициализации при обработке каждой транзакции количество кластеров может как увеличиться, так и остаться неизменным. На этапе итерации функции DeltaAdd/DeltaRemove могут считать параллельно для каждой транзакции.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Вычисление стоимости добавления/удаления транзакции, которые выполняются функциями DeltaAdd/DeltaRemove, происходит независимо для всех &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; кластеров. Поэтому все вычисления можно производить параллельно. Таким образом сложность алгоритма с &amp;lt;math&amp;gt;O(n*k*m)&amp;lt;/math&amp;gt; понижается до &amp;lt;math&amp;gt;O(n*m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; транзакций длины &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; и коэффициент отталкивания &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
метки классов для каждой транзакции в соответствии с проведенной кластеризацией(числовая последовательность длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной сложности алгоритма определяется количеством кластеров: &amp;lt;math&amp;gt;\dfrac{O(n*k*m)}{O(n*m)} = k&amp;lt;/math&amp;gt;&lt;br /&gt;
* [[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]] алгоритма равна &amp;lt;math&amp;gt;\dfrac{nk(m+8) + m + 2}{nm + n + 1} \cong k&amp;lt;/math&amp;gt;&lt;br /&gt;
* Алгоритм не является [[глоссарий#Устойчивость|&#039;&#039;устойчивым&#039;&#039;]], так как результат работы зависит от порядка чтения транзакций и от текущего набора транзакций в кластере.&lt;br /&gt;
* Выполняется свойство сбалансированности операций между параллельными ветвями алгоритма, так как для каждой транзакции выполняются функции DeltaAdd/DeltaRemove, считающие стоимость добавления/удаления транзакции.&lt;br /&gt;
* Свойство [[глоссарий#Детерминированность|&#039;&#039;детерминированности алгоритмов&#039;&#039;]] не выполняется, так как результат алгоритма зависит от порядка прохождения транзакций. Но если рассматривать транзакции как нумерованный список, то результат будет определен однозначно от запуска к запуску. Однако существует расширение алгоритма, обеспечивающее свойство детерминированности. &amp;lt;ref&amp;gt;Li, Y., Le, J., Wang, M. Improving CLOPE’s Profit Value and Stability with an Optimized Agglomerative Approach. Algorithms 2015, 8, 380-394.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
* Так как алгоритм предназначен для кластеризации категориальных данных, то он практически неприменим для числовой кластеризации.&lt;br /&gt;
* Быстро работает даже для большого количества данных, обеспечивая при этом хорошее качество кластеризации&lt;br /&gt;
* Имеет простую реализацию&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
Проверка масштабируемости проводилась на суперкомпьютере &amp;quot;Ломоносов&amp;quot; с числом процессоров 1, 8, 16, 32 и 64. Результаты проверки на графике ниже.&lt;br /&gt;
[[file:Graf_lom.png||700px]]&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
* http://weka.sourceforge.net/doc.stable/weka/clusterers/CLOPE.html - реализация в open source библиотеке для анализа данных WEKA(Waikato Environment for Knowledge Analysis) на языке Java&lt;br /&gt;
Также существуют пользовательские реализации алгоритма:&lt;br /&gt;
* https://github.com/infozor/php_mysql_clustering_clope - реализация алгоритма на PHP&lt;br /&gt;
* https://github.com/Tolsi/scala-clope - реализация алгоритма Scala&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:%D0%9F%D0%B0%D0%B2%D0%B5%D0%BB/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BA%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D0%B9%D0%BD%D1%8B%D1%85_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85_CLOPE&amp;diff=21498</id>
		<title>Участник:Павел/Алгоритм кластеризации категорийных данных CLOPE</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9F%D0%B0%D0%B2%D0%B5%D0%BB/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BA%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D0%B9%D0%BD%D1%8B%D1%85_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85_CLOPE&amp;diff=21498"/>
		<updated>2016-12-27T12:09: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;
Алгоритм CLOPE (Clustering with sLOPE&amp;lt;ref&amp;gt;Yang, Y., Guan, H., You. J. CLOPE: A fast and Effective Clustering Algorithm for Transactional Data In Proc. of SIGKDD’02, July 23-26, 2002, Edmonton, Alberta, Canada.&amp;lt;/ref&amp;gt;) неирархический метод кластеризации, предназначенный для кластеризации огромных наборов категорийных данных. К достоинствам алгоритма относятся высокие масштабируемость и скорость работы и качество кластеризации, что достигается использованием глобального критерия оптимизации на основе максимизации градиента высоты гистограммы кластера. Отличается простотой программной реализации. &lt;br /&gt;
&lt;br /&gt;
Во время работы алгоритм хранит в памяти небольшое количество информации по каждому кластеру и требует минимальное число сканирований набора данных. CLOPE автоматически подбирает количество кластеров, причем это регулируется одним единственным параметром - коэффициентом отталкивания &amp;lt;math&amp;gt; r &amp;lt;/math&amp;gt;. При этом он обеспечивает более высокую производительность и лучшее качество кластеризации в сравнении с многими иерархическими алгоритмами.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
Пусть имеется база транзакций &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, состоящая из множества транзакций &amp;lt;math&amp;gt;\{t_1,t_2,...,t_n\}&amp;lt;/math&amp;gt;. Каждая транзакция есть набор объектов &amp;lt;math&amp;gt;\{i_1,...,i_m\}&amp;lt;/math&amp;gt;. Множество кластеров &amp;lt;math&amp;gt;\{C_1,...,C_k\}&amp;lt;/math&amp;gt; есть разбиение множества &amp;lt;math&amp;gt;\{t_1,...,t_n\}&amp;lt;/math&amp;gt;, такое, что &amp;lt;math&amp;gt;C_1 \cup \dots \cup C_k=\{t_1,...,t_n\}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_i \ne \empty&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_i \cap C_j = \empty &amp;lt;/math&amp;gt;, для &amp;lt;math&amp;gt;i \ge 1, k \ge j&amp;lt;/math&amp;gt;. Каждый элемент &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; называется кластером, а &amp;lt;math&amp;gt;n, m, k&amp;lt;/math&amp;gt; – количество транзакций, количество объектов в базе транзакций и число кластеров соответственно.&lt;br /&gt;
&lt;br /&gt;
Каждый кластер &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; имеет следующие характеристики:&lt;br /&gt;
&amp;lt;math&amp;gt;D(C)&amp;lt;/math&amp;gt; – множество уникальных объектов;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;Occ(i,C)&amp;lt;/math&amp;gt; – количество вхождений (частота) объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; в кластер &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;S(C)= \sum_{i \in D(C)} Occ(i,C)= \sum_{t_i \in C}  \mid t_i  \mid , &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;W(C)=  \mid D(C) \mid ,H(C)=S(C)/W(C) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Функция стоимости:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; Profit(C) = \frac{\sum^{k}_{i=1} G(C_i) \times \mid C_i \mid} {\sum^{k}_{i=1} \mid C_i \mid } = \frac{\sum^{k}_{i=1} \frac{S(C_i)}{W(C_i)^r} \times \mid C_i \mid} {\sum^{k}_{i=1} \mid C_i \mid }  &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;\mid C_i \mid&amp;lt;/math&amp;gt;  количество объектов в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом кластере, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; – количество кластеров, &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; – коэффициент отталкивания &amp;lt;math&amp;gt;(0 &amp;lt; r \le 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С помощью параметра &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; регулируется уровень сходства транзакций внутри кластера, и, как&lt;br /&gt;
следствие, финальное количество кластеров. Этот коэффициент подбирается пользователем. Чем больше &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt;, тем ниже уровень сходства и тем больше кластеров будет сгенерировано.&lt;br /&gt;
&lt;br /&gt;
Постановка задачи кластеризации алгоритмом CLOPE выглядит следующим образом: &lt;br /&gt;
&lt;br /&gt;
для заданных &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; найти разбиение &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; такое, что: &lt;br /&gt;
&amp;lt;math&amp;gt;Profit(C) \longrightarrow max &amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит в вычислении на каждой итерации стоимости добавления и удаления транзакции из кластера: &lt;br /&gt;
&lt;br /&gt;
*вычисление нового размера кластера &amp;lt;math&amp;gt;S_{new}(C_i)=S(C_i) \pm \mid(t_n)\mid &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\mid(t_n)\mid&amp;lt;/math&amp;gt; - длина транзакции&lt;br /&gt;
&lt;br /&gt;
*вычисление новой ширины кластера &amp;lt;math&amp;gt;W_{new}(C_i)=\mid D(C_i \cup t_n)|&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*вычисление стоимости &amp;lt;math&amp;gt;\frac{S_{new}(C_i)(\mid C_i \mid \pm 1)}{W_{new}(C_i)^r} - \frac{S(C_i) \mid C_i \mid }{W(C_i)^r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм состоит из следующих этапов:&lt;br /&gt;
&lt;br /&gt;
1. &#039;&#039;&#039;Инициализация&#039;&#039;&#039;. На этом этапе происходит первый проход по таблице с транзакциями для построения начального разбиения, для каждой транзакции определяется кластер исходя из максимизации стоимости.&lt;br /&gt;
&lt;br /&gt;
2. &#039;&#039;&#039;Итерация&#039;&#039;&#039;. На данном этапе для каждой транзакции проводится попытка перемещения в другой кластер для максимизации функции стоимости.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Первая часть алгоритма - инициализация: для каждой транзакции вычисляется кластер, к которому она будет отнесена исходя из максимизации функции стоимости. Для этого вычисляется вспомогательная функция DeltaAdd, которая считает стоимость добавления транзакции к одному из существующих кластеров, либо к пустому. В итоге транзакция помещается в кластер, для которого цена добавления максимальна.&lt;br /&gt;
&lt;br /&gt;
Вторая часть алгоритма - уточняющие итерации: здесь происходит попытка улучшить вычисленные на первом этапе кластеры. В каждой итерации происходит перебор всех транзакций, и для каждой транзакции вычисляется цена удаления ее из текущего кластера и цена добавления в другой кластер. Суммарная стоимость перемещения будет являться суммой стоимостей удаления и добавления. Если максимальная стоимость перемещения данной транзакции в какой-либо больше нуля, то она перемещается в этот кластер. &lt;br /&gt;
&lt;br /&gt;
Вычисления происходят до тех пор, пока за итерацию происходит хотя бы одно перемещение транзакции. Если за итерацию не было произведено ни одного перемещения, то текущее состояние кластеров является устойчивым и оптимальным. &amp;lt;ref&amp;gt;Павлин Н. Кластеризация категорийных данных: масштабируемый алгоритм CLOPE, https://basegroup.ru/community/articles/clope&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Схема реализации на псевдокоде:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Входные параметры:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - транзакции&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; - коэффициент отталкивания&lt;br /&gt;
&lt;br /&gt;
Выходной параметр:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; кластеры, в начале алгоритма - пустое множество&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация:&#039;&#039;&#039;&lt;br /&gt;
    &#039;&#039;&#039;for&#039;&#039;&#039; t_i in t:&lt;br /&gt;
    max = 0&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; C_j in C:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; DeltaAdd(C_j,t_i,r) &amp;gt; max:&lt;br /&gt;
                max = DeltaAdd(C_j,t_i,r)&lt;br /&gt;
                C_best = C_j&lt;br /&gt;
    &#039;&#039;&#039;put&#039;&#039;&#039; t_i in C_best&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Итерации:&#039;&#039;&#039;&lt;br /&gt;
    move = True&lt;br /&gt;
    &#039;&#039;&#039;while&#039;&#039;&#039; move == True:&lt;br /&gt;
    move = False&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; t_i in t:&lt;br /&gt;
            max = 0&lt;br /&gt;
            C_now = t_i.cluster&lt;br /&gt;
            removeCost = DeltaRemove(C_now,t_i,r)&lt;br /&gt;
            &#039;&#039;&#039;for&#039;&#039;&#039; C_j in C:&lt;br /&gt;
                &#039;&#039;&#039;if&#039;&#039;&#039; DeltaAdd(C_j,t_i,r) + removeCost &amp;gt; max:&lt;br /&gt;
                    max = DeltaAdd(C_j,t_i,r) + removeCost&lt;br /&gt;
                    C_best = C_j&lt;br /&gt;
        if max &amp;gt; 0&lt;br /&gt;
            &#039;&#039;&#039;del&#039;&#039;&#039; t_i from C_now&lt;br /&gt;
            &#039;&#039;&#039;put&#039;&#039;&#039; t_i in C_best&lt;br /&gt;
            move = True&lt;br /&gt;
&lt;br /&gt;
Вспомогательная функция &#039;&#039;&#039;DeltaAdd&#039;&#039;&#039;:&lt;br /&gt;
    &#039;&#039;&#039;function&#039;&#039;&#039; DeltaAdd(C,t,r)&lt;br /&gt;
        S_new=C.size + t.itemCount&lt;br /&gt;
        W_new=C.wigth&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; item in t_i:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; C_j.occ(item) = 0&lt;br /&gt;
                &#039;&#039;W_new = W_new + 1&lt;br /&gt;
        &#039;&#039;&#039;return&#039;&#039;&#039; S_new * (C.count+1) / (W_new ^ r) - (C.size * C.count) / (C.wigth ^ r)&lt;br /&gt;
&lt;br /&gt;
Вспомогательная функция &#039;&#039;&#039;DeltaRemove&#039;&#039;&#039;:&lt;br /&gt;
    &#039;&#039;&#039;function&#039;&#039;&#039; DeltaRemove(C,t,r)&lt;br /&gt;
        S_new=C.size - t.itemCount&lt;br /&gt;
        W_new=C.wigth&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; item in t:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; C_j.occ(item) = 1&lt;br /&gt;
                &#039;&#039;W_new = W_new - 1&lt;br /&gt;
        &#039;&#039;&#039;return&#039;&#039;&#039; S_new * (C.count-1) / (W_new ^ r) - (C.size * C.count) / (C.wigth ^ r)&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
В соответствии с ранее введенным обозначением &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - количество транзакций, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина транзакции(максимальная), &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество кластеров.&lt;br /&gt;
&lt;br /&gt;
Основные вычисления восполняются в функции DeltaAdd/DeltaRemove: производится 1 сложение, не более &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; сложений/вычитаний, 2 умножения, 2 деления, 2 возведения в степень и 1 сложение - итого &amp;lt;math&amp;gt;m + 8&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;k&amp;lt;/math&amp;gt; штук). Итого выполняется &amp;lt;math&amp;gt;n*k*(m+8)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
В добавок к этому при добавлении/удалении транзакции к кластеру производится пересчет его характеристик: &amp;lt;math&amp;gt;m+2&amp;lt;/math&amp;gt; операции.&lt;br /&gt;
&lt;br /&gt;
Из того можно сделать вывод, что оценка сложность алгоритма равна &amp;lt;math&amp;gt;O(n*k*m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
[[File:1_inic.jpg|300px|thumb|left|Инициализация]]&lt;br /&gt;
[[File:2_iter.jpg|300px|thumb|right|Итерации]]&lt;br /&gt;
На этапе инициализации при обработке каждой транзакции количество кластеров может как увеличиться, так и остаться неизменным. На этапе итерации функции DeltaAdd/DeltaRemove могут считать параллельно для каждой транзакции.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Вычисление стоимости добавления/удаления транзакции, которые выполняются функциями DeltaAdd/DeltaRemove, происходит независимо для всех &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; кластеров. Поэтому все вычисления можно производить параллельно. Таким образом сложность алгоритма с &amp;lt;math&amp;gt;O(n*k*m)&amp;lt;/math&amp;gt; понижается до &amp;lt;math&amp;gt;O(n*m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; транзакций длины &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; и коэффициент отталкивания &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
метки классов для каждой транзакции в соответствии с проведенной кластеризацией(числовая последовательность длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной сложности алгоритма определяется количеством кластеров: &amp;lt;math&amp;gt;\dfrac{O(n*k*m)}{O(n*m)} = k&amp;lt;/math&amp;gt;&lt;br /&gt;
* [[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]] алгоритма равна &amp;lt;math&amp;gt;\dfrac{nk(m+8) + m + 2}{nm + n + 1} \cong k&amp;lt;/math&amp;gt;&lt;br /&gt;
* Алгоритм не является [[глоссарий#Устойчивость|&#039;&#039;устойчивым&#039;&#039;]], так как результат работы зависит от порядка чтения транзакций и от текущего набора транзакций в кластере.&lt;br /&gt;
* Выполняется свойство сбалансированности операций между параллельными ветвями алгоритма, так как для каждой транзакции выполняются функции DeltaAdd/DeltaRemove, считающие стоимость добавления/удаления транзакции.&lt;br /&gt;
* Свойство [[глоссарий#Детерминированность|&#039;&#039;детерминированности алгоритмов&#039;&#039;]] не выполняется, так как результат алгоритма зависит от порядка прохождения транзакций. Но если рассматривать транзакции как нумерованный список, то результат будет определен однозначно от запуска к запуску. Однако существует расширение алгоритма, обеспечивающее свойство детерминированности. &amp;lt;ref&amp;gt;Li, Y., Le, J., Wang, M. Improving CLOPE’s Profit Value and Stability with an Optimized Agglomerative Approach. Algorithms 2015, 8, 380-394.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
* Так как алгоритм предназначен для кластеризации категориальных данных, то он практически неприменим для числовой кластеризации.&lt;br /&gt;
* Быстро работает даже для большого количества данных, обеспечивая при этом хорошее качество кластеризации&lt;br /&gt;
* Имеет простую реализацию&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
* http://weka.sourceforge.net/doc.stable/weka/clusterers/CLOPE.html - реализация в open source библиотеке для анализа данных WEKA(Waikato Environment for Knowledge Analysis) на языке Java&lt;br /&gt;
Также существуют пользовательские реализации алгоритма:&lt;br /&gt;
* https://github.com/infozor/php_mysql_clustering_clope - реализация алгоритма на PHP&lt;br /&gt;
* https://github.com/Tolsi/scala-clope - реализация алгоритма Scala&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:%D0%9F%D0%B0%D0%B2%D0%B5%D0%BB/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BA%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D0%B9%D0%BD%D1%8B%D1%85_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85_CLOPE&amp;diff=21497</id>
		<title>Участник:Павел/Алгоритм кластеризации категорийных данных CLOPE</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9F%D0%B0%D0%B2%D0%B5%D0%BB/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BA%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D0%B9%D0%BD%D1%8B%D1%85_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85_CLOPE&amp;diff=21497"/>
		<updated>2016-12-27T11:25:39Z</updated>

		<summary type="html">&lt;p&gt;Павел: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
Автор описания: [[Участник:Павел|П.М.Бронников]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
Алгоритм CLOPE (Clustering with sLOPE&amp;lt;ref&amp;gt;Yang, Y., Guan, H., You. J. CLOPE: A fast and Effective Clustering Algorithm for Transactional Data In Proc. of SIGKDD’02, July 23-26, 2002, Edmonton, Alberta, Canada.&amp;lt;/ref&amp;gt;) неирархический метод кластеризации, предназначенный для кластеризации огромных наборов категорийных данных. К достоинствам алгоритма относятся высокие масштабируемость и скорость работы и качество кластеризации, что достигается использованием глобального критерия оптимизации на основе максимизации градиента высоты гистограммы кластера. Отличается простотой программной реализации. &lt;br /&gt;
&lt;br /&gt;
Во время работы алгоритм хранит в памяти небольшое количество информации по каждому кластеру и требует минимальное число сканирований набора данных. CLOPE автоматически подбирает количество кластеров, причем это регулируется одним единственным параметром - коэффициентом отталкивания &amp;lt;math&amp;gt; r &amp;lt;/math&amp;gt;. При этом он обеспечивает более высокую производительность и лучшее качество кластеризации в сравнении с многими иерархическими алгоритмами.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
Пусть имеется база транзакций &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, состоящая из множества транзакций &amp;lt;math&amp;gt;\{t_1,t_2,...,t_n\}&amp;lt;/math&amp;gt;. Каждая транзакция есть набор объектов &amp;lt;math&amp;gt;\{i_1,...,i_m\}&amp;lt;/math&amp;gt;. Множество кластеров &amp;lt;math&amp;gt;\{C_1,...,C_k\}&amp;lt;/math&amp;gt; есть разбиение множества &amp;lt;math&amp;gt;\{t_1,...,t_n\}&amp;lt;/math&amp;gt;, такое, что &amp;lt;math&amp;gt;C_1 \cup \dots \cup C_k=\{t_1,...,t_n\}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_i \ne \empty&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_i \cap C_j = \empty &amp;lt;/math&amp;gt;, для &amp;lt;math&amp;gt;i \ge 1, k \ge j&amp;lt;/math&amp;gt;. Каждый элемент &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; называется кластером, а &amp;lt;math&amp;gt;n, m, k&amp;lt;/math&amp;gt; – количество транзакций, количество объектов в базе транзакций и число кластеров соответственно.&lt;br /&gt;
&lt;br /&gt;
Каждый кластер &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; имеет следующие характеристики:&lt;br /&gt;
&amp;lt;math&amp;gt;D(C)&amp;lt;/math&amp;gt; – множество уникальных объектов;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;Occ(i,C)&amp;lt;/math&amp;gt; – количество вхождений (частота) объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; в кластер &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;S(C)= \sum_{i \in D(C)} Occ(i,C)= \sum_{t_i \in C}  \mid t_i  \mid , &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;W(C)=  \mid D(C) \mid ,H(C)=S(C)/W(C) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Функция стоимости:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; Profit(C) = \frac{\sum^{k}_{i=1} G(C_i) \times \mid C_i \mid} {\sum^{k}_{i=1} \mid C_i \mid } = \frac{\sum^{k}_{i=1} \frac{S(C_i)}{W(C_i)^r} \times \mid C_i \mid} {\sum^{k}_{i=1} \mid C_i \mid }  &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;\mid C_i \mid&amp;lt;/math&amp;gt;  количество объектов в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом кластере, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; – количество кластеров, &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; – коэффициент отталкивания &amp;lt;math&amp;gt;(0 &amp;lt; r \le 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С помощью параметра &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; регулируется уровень сходства транзакций внутри кластера, и, как&lt;br /&gt;
следствие, финальное количество кластеров. Этот коэффициент подбирается пользователем. Чем больше &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt;, тем ниже уровень сходства и тем больше кластеров будет сгенерировано.&lt;br /&gt;
&lt;br /&gt;
Постановка задачи кластеризации алгоритмом CLOPE выглядит следующим образом: &lt;br /&gt;
&lt;br /&gt;
для заданных &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; найти разбиение &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; такое, что: &lt;br /&gt;
&amp;lt;math&amp;gt;Profit(C) \longrightarrow max &amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит в вычислении на каждой итерации стоимости добавления и удаления транзакции из кластера: &lt;br /&gt;
&lt;br /&gt;
*вычисление нового размера кластера &amp;lt;math&amp;gt;S_{new}(C_i)=S(C_i) \pm \mid(t_n)\mid &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\mid(t_n)\mid&amp;lt;/math&amp;gt; - длина транзакции&lt;br /&gt;
&lt;br /&gt;
*вычисление новой ширины кластера &amp;lt;math&amp;gt;W_{new}(C_i)=\mid D(C_i \cup t_n)|&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*вычисление стоимости &amp;lt;math&amp;gt;\frac{S_{new}(C_i)(\mid C_i \mid \pm 1)}{W_{new}(C_i)^r} - \frac{S(C_i) \mid C_i \mid }{W(C_i)^r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм состоит из следующих этапов:&lt;br /&gt;
&lt;br /&gt;
1. &#039;&#039;&#039;Инициализация&#039;&#039;&#039;. На этом этапе происходит первый проход по таблице с транзакциями для построения начального разбиения, для каждой транзакции определяется кластер исходя из максимизации стоимости.&lt;br /&gt;
&lt;br /&gt;
2. &#039;&#039;&#039;Итерация&#039;&#039;&#039;. На данном этапе для каждой транзакции проводится попытка перемещения в другой кластер для максимизации функции стоимости.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Первая часть алгоритма - инициализация: для каждой транзакции вычисляется кластер, к которому она будет отнесена исходя из максимизации функции стоимости. Для этого вычисляется вспомогательная функция DeltaAdd, которая считает стоимость добавления транзакции к одному из существующих кластеров, либо к пустому. В итоге транзакция помещается в кластер, для которого цена добавления максимальна.&lt;br /&gt;
&lt;br /&gt;
Вторая часть алгоритма - уточняющие итерации: здесь происходит попытка улучшить вычисленные на первом этапе кластеры. В каждой итерации происходит перебор всех транзакций, и для каждой транзакции вычисляется цена удаления ее из текущего кластера и цена добавления в другой кластер. Суммарная стоимость перемещения будет являться суммой стоимостей удаления и добавления. Если максимальная стоимость перемещения данной транзакции в какой-либо больше нуля, то она перемещается в этот кластер. &lt;br /&gt;
&lt;br /&gt;
Вычисления происходят до тех пор, пока за итерацию происходит хотя бы одно перемещение транзакции. Если за итерацию не было произведено ни одного перемещения, то текущее состояние кластеров является устойчивым и оптимальным. &amp;lt;ref&amp;gt;Павлин Н. Кластеризация категорийных данных: масштабируемый алгоритм CLOPE, https://basegroup.ru/community/articles/clope&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Схема реализации на псевдокоде:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Входные параметры:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - транзакции&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; - коэффициент отталкивания&lt;br /&gt;
&lt;br /&gt;
Выходной параметр:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; кластеры, в начале алгоритма - пустое множество&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация:&#039;&#039;&#039;&lt;br /&gt;
    &#039;&#039;&#039;for&#039;&#039;&#039; t_i in t:&lt;br /&gt;
    max = 0&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; C_j in C:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; DeltaAdd(C_j,t_i,r) &amp;gt; max:&lt;br /&gt;
                max = DeltaAdd(C_j,t_i,r)&lt;br /&gt;
                C_best = C_j&lt;br /&gt;
    &#039;&#039;&#039;put&#039;&#039;&#039; t_i in C_best&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Итерации:&#039;&#039;&#039;&lt;br /&gt;
    move = True&lt;br /&gt;
    &#039;&#039;&#039;while&#039;&#039;&#039; move == True:&lt;br /&gt;
    move = False&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; t_i in t:&lt;br /&gt;
            max = 0&lt;br /&gt;
            C_now = t_i.cluster&lt;br /&gt;
            removeCost = DeltaRemove(C_now,t_i,r)&lt;br /&gt;
            &#039;&#039;&#039;for&#039;&#039;&#039; C_j in C:&lt;br /&gt;
                &#039;&#039;&#039;if&#039;&#039;&#039; DeltaAdd(C_j,t_i,r) + removeCost &amp;gt; max:&lt;br /&gt;
                    max = DeltaAdd(C_j,t_i,r) + removeCost&lt;br /&gt;
                    C_best = C_j&lt;br /&gt;
        if max &amp;gt; 0&lt;br /&gt;
            &#039;&#039;&#039;del&#039;&#039;&#039; t_i from C_now&lt;br /&gt;
            &#039;&#039;&#039;put&#039;&#039;&#039; t_i in C_best&lt;br /&gt;
            move = True&lt;br /&gt;
&lt;br /&gt;
Вспомогательная функция &#039;&#039;&#039;DeltaAdd&#039;&#039;&#039;:&lt;br /&gt;
    &#039;&#039;&#039;function&#039;&#039;&#039; DeltaAdd(C,t,r)&lt;br /&gt;
        S_new=C.size + t.itemCount&lt;br /&gt;
        W_new=C.wigth&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; item in t_i:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; C_j.occ(item) = 0&lt;br /&gt;
                &#039;&#039;W_new = W_new + 1&lt;br /&gt;
        &#039;&#039;&#039;return&#039;&#039;&#039; S_new * (C.count+1) / (W_new ^ r) - (C.size * C.count) / (C.wigth ^ r)&lt;br /&gt;
&lt;br /&gt;
Вспомогательная функция &#039;&#039;&#039;DeltaRemove&#039;&#039;&#039;:&lt;br /&gt;
    &#039;&#039;&#039;function&#039;&#039;&#039; DeltaRemove(C,t,r)&lt;br /&gt;
        S_new=C.size - t.itemCount&lt;br /&gt;
        W_new=C.wigth&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; item in t:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; C_j.occ(item) = 1&lt;br /&gt;
                &#039;&#039;W_new = W_new - 1&lt;br /&gt;
        &#039;&#039;&#039;return&#039;&#039;&#039; S_new * (C.count-1) / (W_new ^ r) - (C.size * C.count) / (C.wigth ^ r)&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
В соответствии с ранее введенным обозначением &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - количество транзакций, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина транзакции(максимальная), &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество кластеров.&lt;br /&gt;
&lt;br /&gt;
Основные вычисления восполняются в функции DeltaAdd/DeltaRemove: производится 1 сложение, не более &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; сложений/вычитаний, 2 умножения, 2 деления, 2 возведения в степень и 1 сложение - итого &amp;lt;math&amp;gt;m + 8&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;k&amp;lt;/math&amp;gt; штук). Итого выполняется &amp;lt;math&amp;gt;n*k*(m+8)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
В добавок к этому при добавлении/удалении транзакции к кластеру производится пересчет его характеристик: &amp;lt;math&amp;gt;m+2&amp;lt;/math&amp;gt; операции.&lt;br /&gt;
&lt;br /&gt;
Из того можно сделать вывод, что оценка сложность алгоритма равна &amp;lt;math&amp;gt;O(n*k*m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
[[File:1_inic.jpg|300px|thumb|left|Инициализация]]&lt;br /&gt;
[[File:2_iter.jpg|300px|thumb|right|Итерации]]&lt;br /&gt;
На этапе инициализации при обработке каждой транзакции количество кластеров может как увеличиться, так и остаться неизменным. На этапе итерации функции DeltaAdd/DeltaRemove могут считать параллельно для каждой транзакции.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Вычисление стоимости добавления/удаления транзакции, которые выполняются функциями DeltaAdd/DeltaRemove, происходит независимо для всех &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; кластеров. Поэтому все вычисления можно производить параллельно. Таким образом сложность алгоритма с &amp;lt;math&amp;gt;O(n*k*m)&amp;lt;/math&amp;gt; понижается до &amp;lt;math&amp;gt;O(n*m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; транзакций длины &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; и коэффициент отталкивания &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
метки классов для каждой транзакции в соответствии с проведенной кластеризацией(числовая последовательность длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной сложности алгоритма определяется количеством кластеров: &amp;lt;math&amp;gt;\dfrac{O(n*k*m)}{O(n*m)} = k&amp;lt;/math&amp;gt;&lt;br /&gt;
* [[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]] алгоритма равна &amp;lt;math&amp;gt;\dfrac{nk(m+8) + m + 2}{nm + n + 1} \cong k&amp;lt;/math&amp;gt;&lt;br /&gt;
* Алгоритм не является [[глоссарий#Устойчивость|&#039;&#039;устойчивым&#039;&#039;]], так как результат работы зависит от порядка чтения транзакций и от текущего набора транзакций в кластере.&lt;br /&gt;
* Выполняется свойство сбалансированности операций между параллельными ветвями алгоритма, так как для каждой транзакции выполняются функции DeltaAdd/DeltaRemove, считающие стоимость добавления/удаления транзакции.&lt;br /&gt;
* Свойство [[глоссарий#Детерминированность|&#039;&#039;детерминированности алгоритмов&#039;&#039;]] не выполняется, так как результат алгоритма зависит от порядка прохождения транзакций. Но если рассматривать транзакции как нумерованный список, то результат будет определен однозначно от запуска к запуску. Однако существует расширение алгоритма, обеспечивающее свойство детерминированности. &amp;lt;ref&amp;gt;Li, Y., Le, J., Wang, M. Improving CLOPE’s Profit Value and Stability with an Optimized Agglomerative Approach. Algorithms 2015, 8, 380-394.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
* Так как алгоритм предназначен для кластеризации категориальных данных, то он практически неприменим для числовой кластеризации.&lt;br /&gt;
* Быстро работает даже для большого количества данных, обеспечивая при этом хорошее качество кластеризации&lt;br /&gt;
* Имеет простую реализацию&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;br /&gt;
&lt;br /&gt;
=== Динамические характеристики и эффективность реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Выводы для классов архитектур ===&lt;br /&gt;
&lt;br /&gt;
=== Существующие реализации алгоритма ===&lt;br /&gt;
* http://weka.sourceforge.net/doc.stable/weka/clusterers/CLOPE.html - реализация в open source библиотеке для анализа данных WEKA(Waikato Environment for Knowledge Analysis) на языке Java&lt;br /&gt;
Также существуют пользовательские реализации алгоритма:&lt;br /&gt;
* https://github.com/infozor/php_mysql_clustering_clope - реализация алгоритма на PHP&lt;br /&gt;
* https://github.com/Tolsi/scala-clope - реализация алгоритма Scala&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:%D0%9F%D0%B0%D0%B2%D0%B5%D0%BB/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BA%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D0%B9%D0%BD%D1%8B%D1%85_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85_CLOPE&amp;diff=21496</id>
		<title>Участник:Павел/Алгоритм кластеризации категорийных данных CLOPE</title>
		<link rel="alternate" type="text/html" href="https://xn--80aecvaldz.xn--80ahdrnmvk.xn--p1ai/w/ru/index.php?title=%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:%D0%9F%D0%B0%D0%B2%D0%B5%D0%BB/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%BA%D0%BB%D0%B0%D1%81%D1%82%D0%B5%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8_%D0%BA%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D0%B9%D0%BD%D1%8B%D1%85_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85_CLOPE&amp;diff=21496"/>
		<updated>2016-12-27T11:22:21Z</updated>

		<summary type="html">&lt;p&gt;Павел: Новая страница: «{{Assignment}} Автор описания: П.М.Бронников  = Свойства и структура алгоритмо…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Assignment}}&lt;br /&gt;
Автор описания: [[Участник:Павел|П.М.Бронников]]&lt;br /&gt;
&lt;br /&gt;
= Свойства и структура алгоритмов =&lt;br /&gt;
&lt;br /&gt;
=== Общее описание алгоритма ===&lt;br /&gt;
Алгоритм CLOPE (Clustering with sLOPE&amp;lt;ref&amp;gt;Yang, Y., Guan, H., You. J. CLOPE: A fast and Effective Clustering Algorithm for Transactional Data In Proc. of SIGKDD’02, July 23-26, 2002, Edmonton, Alberta, Canada.&amp;lt;/ref&amp;gt;) неирархический метод кластеризации, предназначенный для кластеризации огромных наборов категорийных данных. К достоинствам алгоритма относятся высокие масштабируемость и скорость работы и качество кластеризации, что достигается использованием глобального критерия оптимизации на основе максимизации градиента высоты гистограммы кластера. Отличается простотой программной реализации. &lt;br /&gt;
&lt;br /&gt;
Во время работы алгоритм хранит в памяти небольшое количество информации по каждому кластеру и требует минимальное число сканирований набора данных. CLOPE автоматически подбирает количество кластеров, причем это регулируется одним единственным параметром - коэффициентом отталкивания &amp;lt;math&amp;gt; r &amp;lt;/math&amp;gt;. При этом он обеспечивает более высокую производительность и лучшее качество кластеризации в сравнении с многими иерархическими алгоритмами.&lt;br /&gt;
&lt;br /&gt;
=== Математическое описание алгоритма ===&lt;br /&gt;
Пусть имеется база транзакций &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt;, состоящая из множества транзакций &amp;lt;math&amp;gt;\{t_1,t_2,...,t_n\}&amp;lt;/math&amp;gt;. Каждая транзакция есть набор объектов &amp;lt;math&amp;gt;\{i_1,...,i_m\}&amp;lt;/math&amp;gt;. Множество кластеров &amp;lt;math&amp;gt;\{C_1,...,C_k\}&amp;lt;/math&amp;gt; есть разбиение множества &amp;lt;math&amp;gt;\{t_1,...,t_n\}&amp;lt;/math&amp;gt;, такое, что &amp;lt;math&amp;gt;C_1 \cup \dots \cup C_k=\{t_1,...,t_n\}&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_i \ne \empty&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;C_i \cap C_j = \empty &amp;lt;/math&amp;gt;, для &amp;lt;math&amp;gt;i \ge 1, k \ge j&amp;lt;/math&amp;gt;. Каждый элемент &amp;lt;math&amp;gt;C_i&amp;lt;/math&amp;gt; называется кластером, а &amp;lt;math&amp;gt;n, m, k&amp;lt;/math&amp;gt; – количество транзакций, количество объектов в базе транзакций и число кластеров соответственно.&lt;br /&gt;
&lt;br /&gt;
Каждый кластер &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; имеет следующие характеристики:&lt;br /&gt;
&amp;lt;math&amp;gt;D(C)&amp;lt;/math&amp;gt; – множество уникальных объектов;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;Occ(i,C)&amp;lt;/math&amp;gt; – количество вхождений (частота) объекта &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt; в кластер &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt;;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;S(C)= \sum_{i \in D(C)} Occ(i,C)= \sum_{t_i \in C}  \mid t_i  \mid , &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;W(C)=  \mid D(C) \mid ,H(C)=S(C)/W(C) &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Функция стоимости:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt; Profit(C) = \frac{\sum^{k}_{i=1} G(C_i) \times \mid C_i \mid} {\sum^{k}_{i=1} \mid C_i \mid } = \frac{\sum^{k}_{i=1} \frac{S(C_i)}{W(C_i)^r} \times \mid C_i \mid} {\sum^{k}_{i=1} \mid C_i \mid }  &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
где &amp;lt;math&amp;gt;\mid C_i \mid&amp;lt;/math&amp;gt;  количество объектов в &amp;lt;math&amp;gt;i&amp;lt;/math&amp;gt;-ом кластере, &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; – количество кластеров, &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; – коэффициент отталкивания &amp;lt;math&amp;gt;(0 &amp;lt; r \le 1)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
С помощью параметра &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; регулируется уровень сходства транзакций внутри кластера, и, как&lt;br /&gt;
следствие, финальное количество кластеров. Этот коэффициент подбирается пользователем. Чем больше &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt;, тем ниже уровень сходства и тем больше кластеров будет сгенерировано.&lt;br /&gt;
&lt;br /&gt;
Постановка задачи кластеризации алгоритмом CLOPE выглядит следующим образом: &lt;br /&gt;
&lt;br /&gt;
для заданных &amp;lt;math&amp;gt;D&amp;lt;/math&amp;gt; и &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; найти разбиение &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; такое, что: &lt;br /&gt;
&amp;lt;math&amp;gt;Profit(C) \longrightarrow max &amp;lt;/math&amp;gt; &amp;lt;ref&amp;gt;Нейский И.М. Классификация и сравнение методов кластеризации.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Вычислительное ядро алгоритма ===&lt;br /&gt;
Вычислительное ядро алгоритма состоит в вычислении на каждой итерации стоимости добавления и удаления транзакции из кластера: &lt;br /&gt;
&lt;br /&gt;
*вычисление нового размера кластера &amp;lt;math&amp;gt;S_{new}(C_i)=S(C_i) \pm \mid(t_n)\mid &amp;lt;/math&amp;gt;, где &amp;lt;math&amp;gt;\mid(t_n)\mid&amp;lt;/math&amp;gt; - длина транзакции&lt;br /&gt;
&lt;br /&gt;
*вычисление новой ширины кластера &amp;lt;math&amp;gt;W_{new}(C_i)=\mid D(C_i \cup t_n)|&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
*вычисление стоимости &amp;lt;math&amp;gt;\frac{S_{new}(C_i)(\mid C_i \mid \pm 1)}{W_{new}(C_i)^r} - \frac{S(C_i) \mid C_i \mid }{W(C_i)^r}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Макроструктура алгоритма ===&lt;br /&gt;
Алгоритм состоит из следующих этапов:&lt;br /&gt;
&lt;br /&gt;
1. &#039;&#039;&#039;Инициализация&#039;&#039;&#039;. На этом этапе происходит первый проход по таблице с транзакциями для построения начального разбиения, для каждой транзакции определяется кластер исходя из максимизации стоимости.&lt;br /&gt;
&lt;br /&gt;
2. &#039;&#039;&#039;Итерация&#039;&#039;&#039;. На данном этапе для каждой транзакции проводится попытка перемещения в другой кластер для максимизации функции стоимости.&lt;br /&gt;
&lt;br /&gt;
=== Схема реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Первая часть алгоритма - инициализация: для каждой транзакции вычисляется кластер, к которому она будет отнесена исходя из максимизации функции стоимости. Для этого вычисляется вспомогательная функция DeltaAdd, которая считает стоимость добавления транзакции к одному из существующих кластеров, либо к пустому. В итоге транзакция помещается в кластер, для которого цена добавления максимальна.&lt;br /&gt;
&lt;br /&gt;
Вторая часть алгоритма - уточняющие итерации: здесь происходит попытка улучшить вычисленные на первом этапе кластеры. В каждой итерации происходит перебор всех транзакций, и для каждой транзакции вычисляется цена удаления ее из текущего кластера и цена добавления в другой кластер. Суммарная стоимость перемещения будет являться суммой стоимостей удаления и добавления. Если максимальная стоимость перемещения данной транзакции в какой-либо больше нуля, то она перемещается в этот кластер. &lt;br /&gt;
&lt;br /&gt;
Вычисления происходят до тех пор, пока за итерацию происходит хотя бы одно перемещение транзакции. Если за итерацию не было произведено ни одного перемещения, то текущее состояние кластеров является устойчивым и оптимальным. &amp;lt;ref&amp;gt;Павлин Н. Кластеризация категорийных данных: масштабируемый алгоритм CLOPE, https://basegroup.ru/community/articles/clope&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Схема реализации на псевдокоде:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Входные параметры:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;t&amp;lt;/math&amp;gt; - транзакции&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt; - коэффициент отталкивания&lt;br /&gt;
&lt;br /&gt;
Выходной параметр:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;math&amp;gt;C&amp;lt;/math&amp;gt; кластеры, в начале алгоритма - пустое множество&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Инициализация:&#039;&#039;&#039;&lt;br /&gt;
    &#039;&#039;&#039;for&#039;&#039;&#039; t_i in t:&lt;br /&gt;
    max = 0&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; C_j in C:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; DeltaAdd(C_j,t_i,r) &amp;gt; max:&lt;br /&gt;
                max = DeltaAdd(C_j,t_i,r)&lt;br /&gt;
                C_best = C_j&lt;br /&gt;
    &#039;&#039;&#039;put&#039;&#039;&#039; t_i in C_best&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Итерации:&#039;&#039;&#039;&lt;br /&gt;
    move = True&lt;br /&gt;
    &#039;&#039;&#039;while&#039;&#039;&#039; move == True:&lt;br /&gt;
    move = False&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; t_i in t:&lt;br /&gt;
            max = 0&lt;br /&gt;
            C_now = t_i.cluster&lt;br /&gt;
            removeCost = DeltaRemove(C_now,t_i,r)&lt;br /&gt;
            &#039;&#039;&#039;for&#039;&#039;&#039; C_j in C:&lt;br /&gt;
                &#039;&#039;&#039;if&#039;&#039;&#039; DeltaAdd(C_j,t_i,r) + removeCost &amp;gt; max:&lt;br /&gt;
                    max = DeltaAdd(C_j,t_i,r) + removeCost&lt;br /&gt;
                    C_best = C_j&lt;br /&gt;
        if max &amp;gt; 0&lt;br /&gt;
            &#039;&#039;&#039;del&#039;&#039;&#039; t_i from C_now&lt;br /&gt;
            &#039;&#039;&#039;put&#039;&#039;&#039; t_i in C_best&lt;br /&gt;
            move = True&lt;br /&gt;
&lt;br /&gt;
Вспомогательная функция &#039;&#039;&#039;DeltaAdd&#039;&#039;&#039;:&lt;br /&gt;
    &#039;&#039;&#039;function&#039;&#039;&#039; DeltaAdd(C,t,r)&lt;br /&gt;
        S_new=C.size + t.itemCount&lt;br /&gt;
        W_new=C.wigth&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; item in t_i:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; C_j.occ(item) = 0&lt;br /&gt;
                &#039;&#039;W_new = W_new + 1&lt;br /&gt;
        &#039;&#039;&#039;return&#039;&#039;&#039; S_new * (C.count+1) / (W_new ^ r) - (C.size * C.count) / (C.wigth ^ r)&lt;br /&gt;
&lt;br /&gt;
Вспомогательная функция &#039;&#039;&#039;DeltaRemove&#039;&#039;&#039;:&lt;br /&gt;
    &#039;&#039;&#039;function&#039;&#039;&#039; DeltaRemove(C,t,r)&lt;br /&gt;
        S_new=C.size - t.itemCount&lt;br /&gt;
        W_new=C.wigth&lt;br /&gt;
        &#039;&#039;&#039;for&#039;&#039;&#039; item in t:&lt;br /&gt;
            &#039;&#039;&#039;if&#039;&#039;&#039; C_j.occ(item) = 1&lt;br /&gt;
                &#039;&#039;W_new = W_new - 1&lt;br /&gt;
        &#039;&#039;&#039;return&#039;&#039;&#039; S_new * (C.count-1) / (W_new ^ r) - (C.size * C.count) / (C.wigth ^ r)&lt;br /&gt;
&lt;br /&gt;
=== Последовательная сложность алгоритма ===&lt;br /&gt;
&lt;br /&gt;
В соответствии с ранее введенным обозначением &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; - количество транзакций, &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; - длина транзакции(максимальная), &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; - количество кластеров.&lt;br /&gt;
&lt;br /&gt;
Основные вычисления восполняются в функции DeltaAdd/DeltaRemove: производится 1 сложение, не более &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; сложений/вычитаний, 2 умножения, 2 деления, 2 возведения в степень и 1 сложение - итого &amp;lt;math&amp;gt;m + 8&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;k&amp;lt;/math&amp;gt; штук). Итого выполняется &amp;lt;math&amp;gt;n*k*(m+8)&amp;lt;/math&amp;gt; операций.&lt;br /&gt;
&lt;br /&gt;
В добавок к этому при добавлении/удалении транзакции к кластеру производится пересчет его характеристик: &amp;lt;math&amp;gt;m+2&amp;lt;/math&amp;gt; операции.&lt;br /&gt;
&lt;br /&gt;
Из того можно сделать вывод, что оценка сложность алгоритма равна &amp;lt;math&amp;gt;O(n*k*m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Информационный граф ===&lt;br /&gt;
[[File:1_inic.jpg|300px|thumb|left|Инициализация]]&lt;br /&gt;
[[File:2_iter.jpg|300px|thumb|right|Итерации]]&lt;br /&gt;
На этапе инициализации при обработке каждой транзакции количество кластеров может как увеличиться, так и остаться неизменным. На этапе итерации функции DeltaAdd/DeltaRemove могут считать параллельно для каждой транзакции.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Ресурс параллелизма алгоритма ===&lt;br /&gt;
&lt;br /&gt;
Вычисление стоимости добавления/удаления транзакции, которые выполняются функциями DeltaAdd/DeltaRemove, происходит независимо для всех &amp;lt;math&amp;gt;k&amp;lt;/math&amp;gt; кластеров. Поэтому все вычисления можно производить параллельно. Таким образом сложность алгоритма с &amp;lt;math&amp;gt;O(n*k*m)&amp;lt;/math&amp;gt; понижается до &amp;lt;math&amp;gt;O(n*m)&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Входные и выходные данные алгоритма ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Входные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; транзакций длины &amp;lt;math&amp;gt;m&amp;lt;/math&amp;gt; и коэффициент отталкивания &amp;lt;math&amp;gt;r&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Выходные данные:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
метки классов для каждой транзакции в соответствии с проведенной кластеризацией(числовая последовательность длины &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
=== Свойства алгоритма ===&lt;br /&gt;
&lt;br /&gt;
* Соотношение последовательной и параллельной сложности алгоритма определяется количеством кластеров: &amp;lt;math&amp;gt;\dfrac{O(n*k*m)}{O(n*m)} = k&amp;lt;/math&amp;gt;&lt;br /&gt;
* [[глоссарий#Вычислительная мощность|&#039;&#039;Вычислительная мощность&#039;&#039;]] алгоритма равна &amp;lt;math&amp;gt;\dfrac{nk(m+8) + m + 2}{nm + n + 1} \cong k&amp;lt;/math&amp;gt;&lt;br /&gt;
* Алгоритм не является [[глоссарий#Устойчивость|&#039;&#039;устойчивым&#039;&#039;]], так как результат работы зависит от порядка чтения транзакций и от текущего набора транзакций в кластере.&lt;br /&gt;
* Выполняется свойство сбалансированности операций между параллельными ветвями алгоритма, так как для каждой транзакции выполняются функции DeltaAdd/DeltaRemove, считающие стоимость добавления/удаления транзакции.&lt;br /&gt;
* Свойство [[глоссарий#Детерминированность|&#039;&#039;детерминированности алгоритмов&#039;&#039;]] не выполняется, так как результат алгоритма зависит от порядка прохождения транзакций. Но если рассматривать транзакции как нумерованный список, то результат будет определен однозначно от запуска к запуску. Однако существует расширение алгоритма, обеспечивающее свойство детерминированности. &amp;lt;ref&amp;gt;Li, Y., Le, J., Wang, M. Improving CLOPE’s Profit Value and Stability with an Optimized Agglomerative Approach. Algorithms 2015, 8, 380-394.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
* Так как алгоритм предназначен для кластеризации категориальных данных, то он практически неприменим для числовой кластеризации.&lt;br /&gt;
* Быстро работает даже для большого количества данных, обеспечивая при этом хорошее качество кластеризации&lt;br /&gt;
* Имеет простую реализацию&lt;br /&gt;
&lt;br /&gt;
= Программная реализация алгоритма =&lt;br /&gt;
&lt;br /&gt;
=== Особенности реализации последовательного алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Локальность данных и вычислений ===&lt;br /&gt;
&lt;br /&gt;
=== Возможные способы и особенности параллельной реализации алгоритма ===&lt;br /&gt;
&lt;br /&gt;
=== Масштабируемость алгоритма и его реализации ===&lt;/div&gt;</summary>
		<author><name>Павел</name></author>
	</entry>
</feed>